![](/img/trans.png)
[英]Configure navigation property for one to many in EF Core 3 not using primary keys?
[英]EF Core One To Many both way navigation is not working
我在 .NET 內核上工作,API 和 EF-CORE
我創建了 DTO 以在 UI 端顯示它。 我正在過濾該 dto 的數據。 問題是我不能為每個表使用兩種導航屬性
我將在兩個例子中解釋我的問題作為一個例子。
假設我有兩個像這樣的 model:
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Blog Blog { get; set; }
public int BlogId { get; set; }
}
然后我正在創建查詢:
這是工作:
var query = await _context.Posts
.Include(c => c.Blog)
.Select(c => new DenemeDto
{
DenemeName=c.Title
}).ToListAsync();
這是行不通的:
var query = await _context.Blogs
.Include(c => c.Posts)
.Select(c => new DenemeDto
{
DenemeName=c.Title
}).ToListAsync();
return Ok(query);
創建方法:
modelBuilder.Entity("Entities.Concrete.Blog", b =>
{ b.Property<int>("BlogId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("BlogId"), 1L, 1);
b.Property<string>("Url")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("BlogId");
b.ToTable("Blogs");});
modelBuilder.Entity("Entities.Concrete.Post", b =>
{ b.Property<int>("PostId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("PostId"), 1L, 1);
b.Property<int>("BlogId")
.HasColumnType("int");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("PostId");
b.HasIndex("BlogId");
b.ToTable("Posts"); });
我想知道為什么?
親切的問候...
您的假設對Include
的作用有些困惑。
var query = await _context.Posts
.Include(c => c.Blog)
.Select(c => new DenemeDto
{
DenemeName=c.Title
}).ToListAsync();
Include
意味着“急切地加載這個親戚”。 當您想要返回實體以便它們的相關實體與它們一起加載時,這適用。 通常,這可能是您正在加載單個博客並想要訪問其帖子的情況:
var blog = await _context.Blog
.Include(b => b.Posts)
.SingleAsync(b => b.BlogId == blogId);
如果沒有Include
,EF 將加載博客,但如果您嘗試訪問它下面的帖子,這將觸發延遲加載(如果啟用)或者只是 #null 或空集合。 延遲加載是一個有用的功能,但會帶來巨大的成本。 如果您知道您將需要相關數據,您可以使用Include
加載它。
當您使用Select
時,您正在做一些不需要急切加載的投影。 EF 將構建一個適合獲取您請求的數據的查詢。 因此,您的查詢可以簡化為:
var query = await _context.Posts
.Select(c => new DenemeDto
{
DenemeName=c.Title
}).ToListAsync();
這有效地轉化為:“從帖子中選擇標題”,當它返回時,EF 將填充 DenemeDto 模型。
所以看看你的第二個例子:
var query = await _context.Blogs
.Include(c => c.Posts)
.Select(c => new DenemeDto
{
DenemeName=c.Title
}).ToListAsync();
同樣, Include
在這里什么也不做,因此您的查詢將轉換為:
“從博客中選擇標題”
如果博客沒有 Title 屬性,這將導致編譯時投訴,或者給你博客的標題,而不是你的帖子。
如果您的帖子沒有對博客的引用,並且您只有 Blog.Posts 可以使用並想要帖子標題:
var query = await _context.Blogs
.SelectMany(c => Posts
.Select( p => new DenemeDto
{
DenemeName=c.Title
}).ToList())
.ToListAsync();
如果您想要 select 博客,但要計算他們的帖子數,則投影如何處理關系的一個更好的例子是:
var query = await _context.Blogs
.Select( b => new BlogDto
{
BlogName = b.Title
PostCount = b.Posts.Count()
}).ToListAsync();
如果我們加載實體,我們會將每個博客和每個帖子加載到 memory 中,只是為了獲取這些信息。 使用上述查詢,EF 將構建一個查詢,該查詢僅返回博客名稱和每個博客的帖子計數。 更快,並且注意我們不需要擔心急切或延遲加載的成本。
在讀取數據時,投影絕對是一個有用的工具,因為它可以幫助 EF 構建更高效的查詢。 急切地加載大量相關數據會創建笛卡爾積,從而導致大量數據從數據庫返回到服務器,然后 EF 必須將其縮減為實體模型。 這需要時間,memory,在許多情況下還需要帶寬。 Select
意味着 EF 可以構建更簡潔的查詢並可能利用數據庫上的索引來節省時間、memory 和帶寬。
在您提供的此示例中:
var query = await _context.Blogs
.Include(c => c.Posts)
.Select(c => new DenemeDto
{
DenemeName=c.Title
}).ToListAsync();
return Ok(query);
c
是Blog
,所以沒有Title
。
我不確定您查詢的目的是什么,但如果您想獲取博客的所有帖子,您可以這樣做:
var query = await _context.Blogs
.SelectMany(x => x.Posts)
.Select(x => new DenemeDto
{
DenemeName = x.Title
})
.ToListAsync();
此外,由於您正在對非實體執行Select
,因此您不需要使用Include
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.