【问题标题】:How to force Entity Framework to map `internal` navigation properties?如何强制实体框架映射“内部”导航属性?
【发布时间】:2014-07-01 21:15:25
【问题描述】:

使用Code FirstEF 5.0 我有以下内容:

internal class Entities : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Project> Projects { get; set; }
}

// User class which holds a list of 'Project' class
public class User
{
    private List<Project> _projects = new List<Project>();

    public int Id { get; set; }
    internal List<Project> Projects
    {
        get { return _projects; }
        set { _projects = value; }
    }
}

// Project class which holds a list of 'Milestone' class
public class Project
{
    private List<Milestone> _milestones = new List<Milestone>();

    public int Id { get; set; }
    public string Title { get; set; }
    internal List<Milestone> MileStones
    {
        get { return _milestones; }
        set { _milestones = value; }
    }
}

虽然 EF 已正确创建表和关系(一对多:用户=>项目=>里程碑)如果我创建一个包含一些项目的用户并将其添加到 DbContext,则只有用户将被添加到他的项目不会。对于具有里程碑的项目的用户也是如此。我是这样做的:

public void AddUser(User user)
{
    using (var repository = new Entities())
    {
        repository.Users.Add(user);
        repository.SaveChanges();
    }
}

我的问题是如何强制EF 自动插入或更新复杂实体(级联),从而添加具有项目列表的用户,自动在 USERS 表中插入用户,在 PROJECTS 表中插入他的项目(具有正确的关系)?

EF 在它的第 5 个版本中那么聪明还是我应该手动完成?

【问题讨论】:

  • 您是否尝试将设置器设置为private
  • @Justin:那行不通。我什至做到了public IReadOnlyListpublic IReadOnlyCollection 尽管我愿意,但EF 拒绝映射只读属性。
  • 您能否将它们公开并更改 get/set 以包含您的验证逻辑?
  • @Justin:一旦我返回集合(在此处列出),我就无法访问修改,除非我通过将其设为只读集合来限制修改。
  • 您能否再解释一下您无法访问修改的原因?

标签: c# insert entity-framework-5 cascade


【解决方案1】:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>().HasMany(x => x.Projects);
}

【讨论】:

  • 这给了你你在哪里寻找的东西?
  • @贾斯汀:是的。这工作正常,无需将internal 变为public
【解决方案2】:

您还可以通过设置“受保护的内部”您的“列出项目”和“列出里程碑”属性来实现所需的结果。这样 EF 就可以处理它们。 EF 将使用代理类包装器覆盖这些属性,并且您还将拥有延迟加载功能。

【讨论】:

    【解决方案3】:

    别担心,EF 足够聪明,但是当它们的访问权限设置为internal 时,它无法添加您的导航属性。将它们设为public,您的项目/里程碑将被添加。

    // User class
    public List<Project> Projects
    {
        get { return _projects; }
        set { _projects = value; }
    }
    
    // Project class
    public List<Milestone> MileStones
    {
        get { return _milestones; }
        set { _milestones = value; }
    }
    

    此外,如果您想在导航属性上启用延迟加载,您还需要将它们设为 public virtual,因为 EF 在内部必须为您的模型类制作代理。

    【讨论】:

    • 它们是internal 的原因是:我需要在允许添加/删除项目/里程碑之前进行一些检查,因此隐藏列表并为此提供两个功能(AddProject/RemoveProject),(AddMilestone /删除里程碑)。有什么方法可以让EFpublic 那样工作吗?
    • 我不这么认为,EF 在检索/更新数据库时需要访问那些设置/获取您的导航属性。
    • EF 可以访问它们,因为代码引用了 EF。但我需要隐藏这些列表以防止直接更改,并提供一些访问它们的方法。是否有任何Data Annotation 强制EF 将它们视为Public?事实上,我应该让他们Private,但由于某种原因,他们让他们Internal
    • 这样使用Code FirstEF 就失去了它的优势。我用它来编码更少而不是更多。无论如何,感谢您的提示 +1。
    • @AlaaMasoud 这里的问题是,在这种情况下,EF 阻止了适当的封装,在我的书中,这严重违反了 OO 原则。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多