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

时间:2017-03-03 19:14:22

标签: c# entity-framework entity-framework-6

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

借款人表

  • BorrowerId(PK和FK)
  • BUSINESSNAME
  • [删除其他列以保持示例简单]

借款人个人表

  • BorrowerId(PK和FK)
  • 全名
  • [删除其他列以保持示例简单]

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

在Code中我有以下内容(我已删除属性以保持示例简单):

[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. 通过设置&#34; db.Entry(entity).State =来更新工作 EntityState.Modified&#34;无需设置状态 BorrowerIndividual?
  2. 有没有办法执行更简单的操作 删除将级联而不显式删除 BorrowerIndividual?
  3. 总的来说,似乎还有更多的工作要做到这一点。

1 个答案:

答案 0 :(得分:1)

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

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修改的所有方案(nullnew - INSERTexistingnull - 做{{ 1}},DELETEexisting - existing)。唯一的缺点是,在最后一种情况下,即使没有更改属性,它也始终为UPDATE生成UPDATE命令。因此,如果您希望以更多代码行的成本优化数据库命令,则可以使用此代码:

BorrowerIndividual

在EF中使用断开连接的实体从未如此简单。