gpt4 book ai didi

c# - Entity Framework 不支持 protected 导航属性吗?

转载 作者:行者123 更新时间:2023-11-30 17:37:11 26 4
gpt4 key购买 nike

我已经声明了一个这样的实体(实际的类显然也有一个ID属性,映射完成等,但这不是问题,所以我在这里跳过它):

public class Parent
{
public virtual ICollection<Child> Children {get; set;}
}

这很完美:

public class Consumer
{
void DoBusiness()
{
using (var ctx = new MyDbContext())
{
var entity = ctx.Parents.Find(keyOfParent);
// This is as expected: entity.Children refers to a collection which
// Entity Framework has assigned, a collection which supports lazy loading.
}
}
}

现在我更改要保护的 Children 集合的可见性:

public class Parent
{
protected virtual ICollection<Child> Children {get; set;}
}

这带来了意想不到的结果:

public class Consumer
{
void DoBusiness()
{
using (var ctx = new MyDbContext())
{
var entity = ctx.Parents.Find(keyOfParent);
// This is NOT as expected: entity.Children is null. I would expect, that it
// had been referring to a collection which Entity Framework would have been
// assigning, a collection which should support lazy loading.
}
}
}

此外,如果我处于保护 child 的情况下,尝试通过以下方式显式加载 child :

ctc.Entry(entity).Collection(x => x.Children)

然后我得到这个异常:

The property "Children" on type 'Parent" is not a navigation property. The Reference and Collection methods can only be used with navigation properties. Use the Property or ComplexProperty method.

因此:为了使用 Entity Framework 获得 protected 导航属性,我究竟应该做什么?

最佳答案

这是我如何让它发挥作用的。

public class Parent
{
public int Id { get; set; }
public string Name { get; set; }

internal ICollection<Child> children;
protected virtual ICollection<Child> Children { get { return children; } set { children = value; } }
internal ICollection<Child> GetChildren() => Children;
internal static Expression<Func<Parent, ICollection<Child>>> ChildrenSelector => p => p.Children;
}

public class Child
{
public int Id { get; set; }
public string Name { get; set; }

internal Parent parent;
protected virtual Parent Parent { get { return parent; } set { parent = value; } }
internal Parent GetParent() => Parent;
internal static Expression<Func<Child, Parent>> ParentSelector => c => c.Parent;
}

public class MyDbContext : DbContext
{
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Children { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>()
.HasMany(Parent.ChildrenSelector)
.WithRequired(Child.ParentSelector)
.Map(a => a.MapKey("ParentId"));

base.OnModelCreating(modelBuilder);
}
}

所使用的显式字段不是必需的 - 我已经放置它们以便能够观察其中的内容,您可以继续使用自动属性。

关键部分是提供属性访问器表达式并将它们与 Fluent API 配置一起使用。如果没有显式配置,您将获得所描述的行为。有了它,一切正常。

例如延迟加载:

var parent = ctx.Parents.Find(keyOfParent);
var children = parent.GetChildren();

或显式加载:

var parent = ctx.Parents.Find(keyOfParent);
db.Entry(parent).Collection("Children").Load();
var children = parent.children;

更新:很奇怪,如果我们替换配置代码

modelBuilder.Entity<Parent>()
.HasMany(Parent.ChildrenSelector)
.WithRequired(Child.ParentSelector)
.Map(a => a.MapKey("ParentId"));

根据定义完全等价

modelBuilder.Entity<Child>()
.HasRequired(Child.ParentSelector)
.WithMany(Parent.ChildrenSelector)
.Map(a => a.MapKey("ParentId"));

数据库表和FK是一样的,但是加载不通!因此,要么工作解决方案意外命中后门,要么 EF 中存在错误。在这两种情况下,该功能对我来说似乎都有问题,我会简单地使用 public 访问器以避免意外。

关于c# - Entity Framework 不支持 protected 导航属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38396165/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com