在断开连接的模型中使用Entity Framework 6的Web应用程序中,我有两个具有一对一关系的表:
借款人表
借款人个人表
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似乎非常典型。更新和删除似乎过于冗长。我能做些什么允许:
总的来说,似乎还有更多的工作要做到这一点。
答案 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
修改的所有方案(null
到new
- INSERT
,existing
到null
- 做{{ 1}},DELETE
到existing
- existing
)。唯一的缺点是,在最后一种情况下,即使没有更改属性,它也始终为UPDATE
生成UPDATE
命令。因此,如果您希望以更多代码行的成本优化数据库命令,则可以使用此代码:
BorrowerIndividual
在EF中使用断开连接的实体从未如此简单。