c# - LazyLoading 在 EFCore 中的行为不符合预期
问题描述
这里有 2 个(最小化的类):
[Index(nameof(Name), IsUnique = true)]
public partial class ParticipantList
{
public ParticipantList()
{
Emails = new HashSet<Email>();
}
[Key]
[Column("id")]
public long Id { get; set; }
//...
[InverseProperty(nameof(Email.ParticipantList))]
public virtual ICollection<Email> Emails { get ; set; }
}
public partial class Email
{
[Key]
[Column("id", TypeName = "integer")]
public long Id { get; set; }
[Column("participant_list_id", TypeName = "integer")]
public long? ParticipantListId { get; set; }
/...
[ForeignKey(nameof(ParticipantListId))]
[InverseProperty("Emails")]
public virtual ParticipantList ParticipantList { get; set; }
}
DbContextOnConfiguring
方法包含:
optionsBuilder
.UseLazyLoadingProxies()
.UseSqlite(...);
DBContextOnModelCreating
方法包含:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Email>(entity =>
{
entity.HasOne(d => d.ParticipantList)
.WithMany(p => p.Emails)
.HasForeignKey(d => d.ParticipantListId)
.OnDelete(DeleteBehavior.ClientSetNull);
});
这是有效的:
var email = _db.Emails.Find(1);
// email.ParticipantList (this lazy loads just fine).
什么不起作用:
var plist = _db.ParticipantLists.Find(1);
// plist.Emails.Count() == 0 (this doesn't lazy load at all)
// plist.Emails.Count == 0 (again no lazy loading)
// plist.Emails.ToList() (empty list, no lazy loading)
我应该在这里插入一个关于 Count() 和 Count 在这里具有不同含义的愚蠢之处。我的意思是,说真的,谁会在代码审查期间发现这一点????
这很可能是由于:
public ParticipantList()
{
Emails = new HashSet<Email>();
}
这是由 ef-scaffold 应用程序创建的。我的意思是它是有道理的,HashSet 是空的,但似乎模型应该覆盖对 HashSet 的访问并进行延迟加载。
问题是,如果你删除它:
public ParticipantList()
{
// Emails = new HashSet<Email>();
}
然后调用此代码:
// plist.Emails.Count() == 0 (Now you get a null reference exception
// because guess what: Emails is not initialized!)
// plist.Emails.ToList() (Also gives a null reference exception)
// plist.Emails.Count == 0 (Again, a null reference exception)
文档显示了这样的代码(请注意,在https://docs.microsoft.com/en-us/ef/core/querying/related-data/lazy的示例中未初始化 Posts ):
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public virtual Blog Blog { get; set; }
}
据称这将延迟加载博客中的帖子。但是,当我遵循该模式并删除初始化电子邮件/帖子的 ctor 时,我得到一个空引用异常。
增加神秘/疯狂的是:
var email = _db.Emails.Find(1);
var plist = _db.ParticipantLists.Find(1);
// plist.Emails.Count() == 1 (It knows about the relation and added it to
// the Emails HashSet on the ParticipantList!)
那么,我如何将电子邮件发送到 LazyLoad。我知道 1 + N 问题,我并不担心这方面,但我希望模型在被请求时加载。
解决方案
推荐阅读
- user-interface - 在 Superset 中,用于共享的 URL 生成为“127.0.0.1:8088”而不是实际域,除了 SQL Lab 中的“共享查询”按钮
- spring-boot - 我们可以在 AWS Lambda 上部署 Spring 微服务吗?
- python - Psycopg2 带有 sql 格式函数的参数化查询
- deeplink - Android-10 DeepLink 不工作...,但在 android 10 版本以下工作
- typescript - Vetur 在模板中无法正常工作(不检查数据、方法...)
- sql - 自定义排序的清洁方式
- php - 找不到类“Illuminate\Http\Response”
- java - 如何为以下内容编写改造功能
- c# - ToolStripTextBox 中的自定义绘制
- uwp - 错误 CS5001:程序不包含适用于入口点的静态“Main”方法