Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions dotnet-efcore/VirtualKeywordInEFCore/Tests/Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand All @@ -10,10 +10,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
<PackageReference Include="coverlet.collector" Version="10.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,40 @@ public void GivenLazyLoading_WithLazyLoadingEnabledPropertySetToFalse_WhenAuthor
Assert.False(authorHollyJackson.Books.Any());
Assert.Empty(authorHollyJackson.Books);
}

[Fact]
public void GivenInjectedLazyLoader_WhenAuthorRetrievedInFreshContext_ThenBooksLazyLoadedWithoutProxy()
{
// Arrange
using (var seedContext = new DataContextInjected())
{
DataSeeder.SeedInjected(seedContext);
}

using var context = new DataContextInjected();

// Act
var author = context.AuthorsInjected.First(a => a.FullName == "Freida MCFADDEN");

// Assert
Assert.Equal(typeof(AuthorInjected), author.GetType());
Assert.NotNull(author.Books);
Assert.Equal(2, author.Books.Count);
}

[Fact]
public void GivenNoLazyLoading_WhenCollectionExplicitlyLoaded_ThenEmptyCollectionIsFilled()
{
// Arrange
using var context = new DataContextWithoutLazyLoading();
var author = context.Authors.First(a => a.FullName == "Lucy FOLEY");
Assert.Empty(author.Books);

// Act
context.Entry(author).Collection(a => a.Books).Load();

// Assert
Assert.Equal(4, author.Books.Count);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace VirtualKeywordInEFCore.Models
{
public class AuthorInjected
{
private ICollection<BookInjected>? _books;

public AuthorInjected() { }

private AuthorInjected(ILazyLoader lazyLoader) => LazyLoader = lazyLoader;

private ILazyLoader? LazyLoader { get; set; }

public int AuthorInjectedId { get; set; }
public string? FullName { get; set; }

public ICollection<BookInjected>? Books
{
get => LazyLoader.Load(this, ref _books);
set => _books = value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ public class Book
public int BookId { get; set; }
public string? Title { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
public Author Author { get; set; } = null!;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace VirtualKeywordInEFCore.Models
{
public class BookInjected
{
public int BookInjectedId { get; set; }
public string? Title { get; set; }
public int AuthorInjectedId { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ public class BookLazy
public int BookId { get; set; }
public string? Title { get; set; }
public int AuthorId { get; set; }
public virtual AuthorLazy Author { get; set; }
public virtual AuthorLazy Author { get; set; } = null!;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore;

namespace VirtualKeywordInEFCore.Models
{
public class DataContextInjected : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite("DataSource=LibraryInjected.db");

base.OnConfiguring(options);
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AuthorInjected>()
.HasMany(a => a.Books)
.WithOne()
.HasForeignKey(b => b.AuthorInjectedId);
}

public DbSet<AuthorInjected> AuthorsInjected { get; set; }
public DbSet<BookInjected> BooksInjected { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,27 @@ public static void SeedLazy(DataContextLazyLoading contextLazy)
contextLazy.AddRange(booksLazy);
contextLazy.SaveChanges();
}

public static void SeedInjected(DataContextInjected contextInjected)
{
contextInjected.Database.EnsureCreated();
if (contextInjected.AuthorsInjected.Any())
{
return;
}

var authorInjected = new AuthorInjected
{
FullName = "Freida MCFADDEN",
Books = new List<BookInjected>
{
new () { Title = "The Housemaid" },
new () { Title = "The Coworker" }
}
};

contextInjected.Add(authorInjected);
contextInjected.SaveChanges();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
LoadData();

LoadDataWithLazyLoading();

LoadDataWithInjectedLazyLoader();
LoadDataWithExplicitLoading();
}

public static void LoadData()
Expand All @@ -21,15 +24,12 @@
Author author;
author = contextWithoutLazyLoading.Authors.AsNoTracking().First(a => a.FullName == "Lucy FOLEY");

if (author is not null)
{
Console.WriteLine($"Author Name: {author.FullName}");
Console.WriteLine($"{author.FullName}'s Books number: {author.Books.Count}");
Console.WriteLine($"Author Name: {author.FullName}");
Console.WriteLine($"{author.FullName}'s Books number: {author.Books.Count}");

foreach (var book in author.Books)
{
Console.WriteLine($"Book Title: {book.Title}");
}
foreach (var book in author.Books)
{
Console.WriteLine($"Book Title: {book.Title}");
}
}

Expand All @@ -49,11 +49,44 @@
Console.WriteLine($"{nameof(AuthorLazy)} datatype: {authorLazy.GetType()}");
Console.WriteLine($"{nameof(BookLazy)} datatype: {authorLazy.Books?.First().GetType()}");

foreach (var bookLazy in authorLazy.Books)

Check warning on line 52 in dotnet-efcore/VirtualKeywordInEFCore/VirtualKeywordInEFCore/Program.cs

View workflow job for this annotation

GitHub Actions / Build & test (dotnet-efcore/VirtualKeywordInEFCore)

Dereference of a possibly null reference.

Check warning on line 52 in dotnet-efcore/VirtualKeywordInEFCore/VirtualKeywordInEFCore/Program.cs

View workflow job for this annotation

GitHub Actions / Build & test (dotnet-efcore/VirtualKeywordInEFCore)

Dereference of a possibly null reference.
{
Console.WriteLine($"Book Title: {bookLazy.Title}");
}
}
}

public static void LoadDataWithInjectedLazyLoader()
{
Console.WriteLine("\nLazy Loading with an injected ILazyLoader:");

using (var seedContext = new DataContextInjected())
{
DataSeeder.SeedInjected(seedContext);
}

using var context = new DataContextInjected();
var author = context.AuthorsInjected.First(a => a.FullName == "Freida MCFADDEN");

Console.WriteLine($"{nameof(AuthorInjected)} datatype: {author.GetType()}");
Console.WriteLine($"{author.FullName}'s Books number: {author.Books?.Count}");
}

public static void LoadDataWithExplicitLoading()
{
Console.WriteLine("\nExplicit Loading:");

using (var seedContext = new DataContextWithoutLazyLoading())
{
DataSeeder.SeedWithoutLazy(seedContext);
}

using var context = new DataContextWithoutLazyLoading();
var author = context.Authors.First(a => a.FullName == "Lucy FOLEY");

context.Entry(author).Collection(a => a.Books).Load();

Console.WriteLine($"{author.FullName}'s Books number after Load(): {author.Books.Count}");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="10.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="10.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.12" />
</ItemGroup>

</Project>
Loading