简化实体框架 6 一对一关系的语法

乔希

在一个在断开连接的模型中使用实体框架 6 的 Web 应用程序中,我有两个具有一对一关系的表:

借款人表

  • BorrowerId(PK和FK)
  • 企业名称
  • [为了简化示例,删除了其他列]

借款人个人表

  • BorrowerId(PK和FK)
  • 全名
  • [为了简化示例,删除了其他列]

FK 关系在 BorrowerId 上。总会有借款人记录,但偶尔只有借款人记录。我在关系上定义了级联删除。

在代码中,我有以下内容(我删除了属性以保持示例简单):

[Serializable]
public class BusinessBorrower
{
  [Key]
  [Column("BusinessBorrowerId")]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int? Id { get; set; }

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

[Serializable]
public class BusinessBorrowerIndividual
{
  [Key]
  [Column("BusinessBorrowerId")]
  [DatabaseGenerated(DatabaseGeneratedOption.None)]
  public int? Id { get; set; }

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

在我的存储库类中,我有以下 CRUD 操作:

public class BusinessBorrowerRepository
{
    public Borrower GetById(int id)
    {
        Borrower item;

        using (var db = new MainContext())
        {
            item = db.Borrowers
                        .Include(b => b.BorrowerIndividual)
                        .FirstOrDefault(f => f.Id == id);
        }

        return item;
    }

    public int Add(Borrower entity)
    {
        int id;

        using (var db = new MainContext())
        {
            db.Entry(entity).State = EntityState.Added;

            db.SaveChanges();

            id = (int)entity.Id;
        }

        return id;
    }

    public bool Update(Borrower entity)
    {
        using (var db = new MainContext())
        {
            if (entity.BorrowerIndividual != null)
            {
                entity.BorrowerIndividual.Id = entity.Id; // share same key, set to match

                // Test if record exists in db to determine if added or modified
                var exists = db.BorrowerIndividuals.Any(i => i.Id == entity.BorrowerIndividual.Id.Value);
                db.Entry(entity.BorrowerIndividual).State = exists ? EntityState.Modified : EntityState.Added;
            }

            db.Entry(entity).State = EntityState.Modified;

            db.SaveChanges();
        }

        return true;
    }

    public bool Delete(int id)
    {
        using (var db = new MainContext())
        {
            var entity = GetById(id);

            if (entity.BorrowerIndividual != null)
            {
                db.BorrowerIndividuals.Attach(entity.BorrowerIndividual);
                db.BorrowerIndividuals.Remove(entity.BorrowerIndividual);
                entity.BorrowerIndividual = null;
            }

            db.Borrowers.Attach(entity);
            db.Borrowers.Remove(entity);

            db.SaveChanges();
        }

        return true;
    }
}

dbContext类:

internal class MainContext : DbContext
{
   internal MainContext() : base("name=SqlServer")
   {
     Database.SetInitializer<MainContext>(null);
   }

   public virtual DbSet<Borrower> Borrowers { get; set; }
   public virtual DbSet<BorrowerIndividual> BorrowerIndividuals { get; set; }

   protected override void OnModelCreating(DbModelBuilder modelBuilder)
   {
     Database.SetInitializer<MainContext>(null); 

     modelBuilder.Configurations.Add(new BorrowerConfiguration());

     base.OnModelCreating(modelBuilder);
   }
}

class BorrowerConfiguration : EntityTypeConfiguration<Borrower>
{
  internal BusinessBorrowerConfiguration()
  {
    this.HasRequired(x => x.BorrowerIndividual).WithRequiredPrincipal();   
  }
}

GetById 和 Add 看起来很典型。更新和删除似乎过于冗长。有什么我可以做的事情允许:

  1. 更新只需设置“db.Entry(entity).State = EntityState.Modified”而无需设置 BorrowerIndividual 的状态?
  2. 有没有办法执行更简单的删除,该删除将在不明确删除 BorrowerIndividual 的情况下进行级联?

总的来说,似乎需要做更多的工作才能让它发挥作用。

伊万·斯托耶夫

这两种方法都可以简化。但首先确保级联删除已打开(因为默认情况下它不是):

modelBuilder.Entity<Borrower>()
    .HasRequired(x => x.BorrowerIndividual)
    .WithRequiredPrincipal()
    .WillCascadeOnDelete();

现在有问题的方法。

删除:

由于您使用的是专门分配的短期活动DbContext,您可以使用所谓的存根实体:

db.Entry(new Borrower { Id = id }).State = EntityState.Deleted;
db.SaveChanges();

但请注意,如果没有指定的记录,它将失败并出现异常Id所以更安全的版本应该是这样的(不要使用GetById使用不同上下文的方法,也不要Include使用相关数据,因为我们将依赖于数据库级联删除):

var existing = db.Borrowers.FirstOrDefault(e => e.Id == id);
if (existing == null) return; // ??
db.Borrowers.Remove(existing);
db.SaveChanges();

更新:

var existing = db.Borrowers.Include(e => e.BorrowerIndividual).FirstOrDefault(e => e.Id == entity.Id);
if (existing == null) return; // ??
db.Entry(existing).CurrentValues.SetValues(entity);
existing.BorrowerIndividual = entity.BorrowerIndividual;
db.SaveChanges();

这适用于所有BorrowerIndividual修改场景nullto new-dos INSERTexistingto null-dos DELETEexistingto existing-dos UPDATE)。唯一的缺点是,在最后一种情况下,即使没有更改任何属性UPDATE,它BorrowerIndividual也会始终为 生成命令因此,如果您要花费更多的代码行来优化数据库命令,则可以改用以下命令:

var existing = db.Borrowers.Include(e => e.BorrowerIndividual).FirstOrDefault(e => e.Id == entity.Id);
db.Entry(existing).CurrentValues.SetValues(entity);
if (existing == null) return; // ??
if (existing.BorrowerIndividual != null && entity.BorrowerIndividual != null)
{
    entity.BorrowerIndividual.Id = existing.Id;
    db.Entry(existing.BorrowerIndividual).CurrentValues.SetValues(entity.BorrowerIndividual);
}
else
    existing.BorrowerIndividual = entity.BorrowerIndividual;
db.SaveChanges();

在 EF 中处理断开连接的实体从来都不是一件容易的事。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

实体框架6:具有继承关系的一对一关系

来自分类Dev

实体框架代码优先一对一关系

来自分类Dev

实现实体框架一对一关系

来自分类Dev

一对一关系实体框架

来自分类Dev

实体框架中的一对一关系插入

来自分类Dev

实体框架核心一对一关系在SQL Server中生成一对多

来自分类Dev

如何删除一对一关系中的实体?

来自分类Dev

无法在实体之间建立一对一关系

来自分类Dev

Django rest框架一对一关系

来自分类Dev

实体框架代码首先在复杂实体之间建立一对一关系

来自分类Dev

一对一实体框架关系

来自分类Dev

实体框架与ASP.NET Boilerplate的一对一关系

来自分类Dev

实体框架两端可选的一对一关系

来自分类Dev

实体框架首先使用代码一对一关系。怎么样?

来自分类Dev

C#实体框架:可选的一对一关系

来自分类Dev

实体框架与ASP.NET Boilerplate的一对一关系

来自分类Dev

实体框架:一对一关系,能够双向导航

来自分类Dev

实体框架以一对一关系添加新记录,而对象具有 ID

来自分类Dev

一对零或一对一关系的实体框架(EF)代码优先级联删除

来自分类Dev

实体框架-在种子方法中将现有实体添加到一对一关系

来自分类Dev

实体框架-在种子方法中将现有实体添加到一对一关系

来自分类Dev

实体框架一对一关系,其中一个为可选抛出错误

来自分类Dev

在Entity Framework 6 Code First中创建一对一关系时出错

来自分类Dev

在Hibernate中保持一对一关系实体-实体分离

来自分类Dev

SQLite-Net Extension两个实体之间的一对一关系和一对多关系

来自分类Dev

如何在实体框架中定义表达式选择嵌套的一对一关系

来自分类Dev

如何更改与自己的实体框架7(ASP.NET Core)一对一关系创建的记录?

来自分类Dev

应用迁移到数据库的一对一关系时,由实体框架生成的迁移崩溃

来自分类Dev

JPA:如何保存具有一对一关系的两个实体?

Related 相关文章

  1. 1

    实体框架6:具有继承关系的一对一关系

  2. 2

    实体框架代码优先一对一关系

  3. 3

    实现实体框架一对一关系

  4. 4

    一对一关系实体框架

  5. 5

    实体框架中的一对一关系插入

  6. 6

    实体框架核心一对一关系在SQL Server中生成一对多

  7. 7

    如何删除一对一关系中的实体?

  8. 8

    无法在实体之间建立一对一关系

  9. 9

    Django rest框架一对一关系

  10. 10

    实体框架代码首先在复杂实体之间建立一对一关系

  11. 11

    一对一实体框架关系

  12. 12

    实体框架与ASP.NET Boilerplate的一对一关系

  13. 13

    实体框架两端可选的一对一关系

  14. 14

    实体框架首先使用代码一对一关系。怎么样?

  15. 15

    C#实体框架:可选的一对一关系

  16. 16

    实体框架与ASP.NET Boilerplate的一对一关系

  17. 17

    实体框架:一对一关系,能够双向导航

  18. 18

    实体框架以一对一关系添加新记录,而对象具有 ID

  19. 19

    一对零或一对一关系的实体框架(EF)代码优先级联删除

  20. 20

    实体框架-在种子方法中将现有实体添加到一对一关系

  21. 21

    实体框架-在种子方法中将现有实体添加到一对一关系

  22. 22

    实体框架一对一关系,其中一个为可选抛出错误

  23. 23

    在Entity Framework 6 Code First中创建一对一关系时出错

  24. 24

    在Hibernate中保持一对一关系实体-实体分离

  25. 25

    SQLite-Net Extension两个实体之间的一对一关系和一对多关系

  26. 26

    如何在实体框架中定义表达式选择嵌套的一对一关系

  27. 27

    如何更改与自己的实体框架7(ASP.NET Core)一对一关系创建的记录?

  28. 28

    应用迁移到数据库的一对一关系时,由实体框架生成的迁移崩溃

  29. 29

    JPA:如何保存具有一对一关系的两个实体?

热门标签

归档