在一个在断开连接的模型中使用实体框架 6 的 Web 应用程序中,我有两个具有一对一关系的表:
借款人表
借款人个人表
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 看起来很典型。更新和删除似乎过于冗长。有什么我可以做的事情允许:
总的来说,似乎需要做更多的工作才能让它发挥作用。
这两种方法都可以简化。但首先确保级联删除已打开(因为默认情况下它不是):
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
to new
-dos INSERT
、existing
to null
-dos DELETE
、existing
to 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] 删除。
我来说两句