c# - Entity Framework - 一对多关系的问题

标签 c# entity-framework lazy-loading virtual one-to-many

我们采用代码优先的方法,但在处理一对多关系时遇到了麻烦。

  • 一个部门 (Dep) 有一个员工列表。
  • 每个员工都属于一个部门。 (必填)
  • 我想更新员工姓名。 (不接触部门)

我已将样本缩减为一些简单的类:

public class Employee
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string name { get; set; }

    [Required]
    public virtual Dep dep { get; set; }

}

public class Dep
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string name { get; set; }

    public virtual ICollection<Employee> Employees { get; set; }
}

添加新值可以像这样正常工作:

Dep dep = new Dep { name = "My Departement" };
Employee employee = new Employee { name = "My name" };
dep.Employees.Add(employee);

context.Deps.Add(dep);
context.SaveChanges();

但是,如果我们想要更新 Employee,就会遇到麻烦。

// Get Employee by Id
Employee employee = Repository.Employees.Single(p => p.Id ==<some id>);
employee.name = "My new name";
context.SaveChanges();

问题 1:

如果我们使用

  • public virtual Dep dep { get;放;

在上面的代码中,我们注意到 Dep 对象在调试时可以从 Employee 获得。当我们浏览对象时,Dep 加载正常。

但是如果我们像这样从 Employee 类中删除 virtual:

  • public Dep dep { get;放;

,则 Dep 始终为 null。奇怪!

为什么会这样? virtual 不就是决定相关数据要不要懒加载吗?

问题二

既然我们无论如何都想使用虚拟,那么麻烦就从保存更新的 Employee 开始。它总是失败并显示需要 Dep 的消息。 Employee 已经有一个 Dep,我不想惹它。我只想更改员工的姓名。没有别的......

为什么保存Employee时会丢失Dep关系?

我可以在使用虚拟时让它工作,如果我确保 Dep 也由

手动加载
  1. 添加一些代码以读取 Dep 对象中的一些值

  1. 调试和浏览 Dep 对象

但这一切真的有必要吗?在这种情况下,我真的不关心 Dep 关系。为什么我必须加载 Dep 数据?

最佳答案

问题二:

这是因为您使用了 [Required] 属性。在这种情况下,您要求框架(不仅是 EF)处理所需的约束。

如果您只想在 EF 级别应用约束,您应该使用流畅的 API:

public class testEF : DbContext {
    public IDbSet<Employee> Employees { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Configurations.Add(new EmployeeEFConfiguration());
    }
}

public class EmployeeEFConfiguration : EntityTypeConfiguration<Employee> {
    public EmployeeEFConfiguration() {
        HasRequired(x => x.Dep).WithMany(y => y.Employees);
    }
}

我刚刚做了测试。以前的代码运行。如果我使用 RequiredAttribute,我会遇到与您相同的异常。

完整示例:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.Linq;

namespace testEf6 {
    class Program {
        static void Main(string[] args) {
            using (testEF ctx = new testEF()) {
                C2 c2 = new C2 {
                    Name = "old name",
                    C1 = new C1 { }
                };

                ctx.C2s.Add(c2);
                ctx.SaveChanges();
            }

            using (testEF ctx = new testEF()) {
                C2 c2 = ctx.C2s.First();
                c2.Name = "new name";
                ctx.SaveChanges(); // exception here with the attribute ========
            }
        }
    }

    public class testEF : DbContext {
        public IDbSet<C2> C2s { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
            //modelBuilder.Configurations.Add(new C2EFConfiguration());
        }
    }

    public class C2EFConfiguration : EntityTypeConfiguration<C2> {
        public C2EFConfiguration() {
            HasRequired(x => x.C1).WithMany(y => y.C2s);
        }
    }

    public class C1 {
        public int Id { get; set; }
        public virtual ICollection<C2> C2s { get; set; }
    }

    public class C2 {
        public int Id { get; set; }
        public String Name { get; set; }
        [Required] 
        public virtual C1 C1 { get; set; }

    }
}

关于c# - Entity Framework - 一对多关系的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29967651/

相关文章:

.net - 温莎城堡的延迟加载服务

java - 如何使用 JUnit 与 Spring 和 Hibernate 来模拟事务的结束以隔离 LazyInitializationException?

c# - 更新 ASP.NET 4 中的单个数据库列

error-handling - 如何处理 Primefaces 延迟加载中的错误?

c# - 使用c#对服务器时间进行操作

c# - 是否可以在 visual studio 的构建输出中使用 "collapse"内容文件路径?

c# - 在可移植库中使用适用于 .NET 的 Google API 客户端库

c# - 调用 Caffe 的 C++/CLI 包装器时出现 AccessViolationException

c# - EntityFramework 种子 AddOrUpdate 与外键

c# - Entity Framework 父子表仅返回直接子项