【发布时间】:2023-03-08 03:44:01
【问题描述】:
我有两个实体 Employee 和 Asset。它们被定义为:
public class Employee
{
public Employee()
{
this.Assets = new List<Asset>();
}
public int EmployeeID { get; set; }
public string Name { get; set; }
public virtual List<Asset> Assets { get; set; }
}
public class Asset
{
public string FacilityAssetID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Fluent 将架构定义为:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>().ToTable("Employees");
modelBuilder.Entity<Employee>().HasKey(e => e.EmployeeID);
modelBuilder.Entity<Employee>().Property(e => e.Name).HasMaxLength(50).IsRequired();
modelBuilder.Entity<Employee>().HasMany(e => e.Assets).WithMany().Map(m => m.MapLeftKey("EmployeeID").MapRightKey("FacilityAssetID").ToTable("EmployeeToAsset"));
modelBuilder.Entity<Asset>().ToTable("Assets");
modelBuilder.Entity<Asset>().HasKey(a => a.FacilityAssetID);
modelBuilder.Entity<Asset>().Property(a => a.Name).HasMaxLength(50).IsRequired();
modelBuilder.Entity<Asset>().Property(a => a.Description).HasMaxLength(200).IsRequired();
base.OnModelCreating(modelBuilder);
}
现在,我有一些员工和一些资产。使用 Web 服务填充资产。假设我有以下资产:
- {FacilityAssetID}、{Name}、{Description}
- Asset1F32,主轴头,SomeDesc
- Asset1C53,铣削块,SomeDesc
有两个具有 ID 的资产:Asset1F32 和 Asset1C53。如果我尝试使用以下代码向员工添加资产,我可以成功添加资产:
using (VCContext context = new VCContext())
{
Employee emp = context.Employees.First();
Asset assetDetached = new Asset() { FacilityAssetID = "Asset1F32" };
context.Assets.Attach(assetDetached);
emp.Assets.Add(assetDetached);
context.SaveChanges();
}
如果我事先循环了一些资产并尝试添加资产,它将引发异常。这是代码:
using (VCContext context = new VCContext())
{
foreach (Employee employee in context.Employees)
{
Console.WriteLine(employee.Name);
foreach (Asset asset in employee.Assets)
{
Console.WriteLine(string.Format(" - {0}", asset.FacilityAssetID));
}
}
Employee emp = context.Employees.First();
Asset assetDetached = new Asset() { FacilityAssetID = "Asset1F32" };
context.Assets.Attach(assetDetached); // EXCEPTION HERE!!!
emp.Assets.Add(assetDetached);
context.SaveChanges();
}
抛出的异常是:
附加类型为“ASTC.Asset”的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后将非新实体的状态设置为“未更改”或“已修改”。
为什么它会在第二种情况下抛出异常而不是第一种情况?另外,如何在第二种情况下添加分离的资产?
【问题讨论】:
-
你为什么在这里调用 Attach()?您的实体是在同一上下文中创建和查询的,因此无需附加它们。
-
唯一被创建和查询的实体是
Employee.Asset未被查询。这是我崩溃的一个简短示例。实际上,我正在遍历数据库的当前资产列表并与另一个异地列表进行比较。如果有需要添加的,我正在尝试添加。 -
是的,但我的意思是,如果您想添加尚未在数据库中的资产,只需致电
emp.Assets.Add(new Asset()),没有理由先附加它。Attach()函数用于已在数据库中但已在另一个上下文中查询的实体。 -
嗨,弗洛里安。它可能已经在数据库中,但可能尚未与该员工关联。
-
好的,我明白了 :-) 你想使用实体存根来建立你的关联。抛出此异常是因为您尝试为已在
foreach循环中加载的实体附加存根。因此,要解决此问题,您必须检查加载的实体并使用完整实体而不是存根并将其与员工关联。
标签: c# entity-framework