好吧,我有以下模型结构:我有一个类 - DatabaseEntity
基本上是
public class DatabaseEntity
{
public int Id { get; set; }
}
所以每个实体(如产品,类别等)都会继承DatabaseEntity
并具有Id
属性。此外,我还有EntityFramework
方法的典型InsertOrUpdate
存储库类:
private readonly DbContext _database;
public void InsertOrUpdate<TObject>(TObject entity) where TObject : DatabaseEntity
{
if(entity.Id == default(int))
{
// New entity
DbSet<TObject>().Add(entity);
}
else
{
// Existing entity
_database.Entry(entity).State = EntityState.Modified;
}
_database.SaveChanges();
}
然后我从eBay下载eBay api列表,我必须添加到数据库中。基本上类别是:
public class EbayCategory : DatabaseEntity
{
// It has Id since it inherits DatabaseEntity
public string Name { get; set; }
// ... some other properties
}
但问题是,当我下载这些类别时,我下载了他们的Id属性,当然,这些属性已经有了价值。当我尝试将它们保存到数据库时:
public void UpdateCategories(IEnumerable<EbayCategory> newCategories)
{
foreach (var newCategory in newCategories)
{
_repository.InsertOrUpdate(newCategory);
}
}
我面临一些问题......首先,entity.Id != default(int)
因为它有价值,所以存储库尝试更新此实体,而不是添加,但它不在数据库或上下文中,因此它会抛出以下内容例外:
System.Data.Entity.Infrastructure.DbUpdateConcurencyException
"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."
...因为它认为其他人删除了我想要更新的实体。如何保存此InsertOrUpdate逻辑,因为许多项目都基于它,并且能够将带有主键(EbayCategories
)的项目(Id
)添加到数据库,然后像更新/删除它们一样其他实体没有放弃EbayCategory.Id
值?
答案 0 :(得分:9)
要允许您手动生成ID,您需要一个具有手动生成ID的类 - 因此它无法继承DatabaseEntity
public class EbayCategory
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public string Name { get; set; }
// ... some other properties
}
现在,您将需要一个不同的InsertOrUpdate
来处理具有手动生成密钥的实体:
public void InsertOrUpdate(EbayCategory entity)
{
if(Find(entity.ID == null)
{
// New entity
DbSet<EbayCategory>().Add(entity);
}
else
{
// Existing entity
_database.Entry(entity).State = EntityState.Modified;
}
_database.SaveChanges();
}
答案 1 :(得分:4)
Colin上面的答案非常正确地说明了如何使用数据注释来实现此设置。 但是在提出的问题中,实体是子类,因此您无法在不更改实体类的情况下添加注释。
还有另一种配置方法:Fluent配置。这是我使用EntityTypeConfiguration类的示例:
public class LookupSchoolsConfiguration : EntityTypeConfiguration<LookupSchools>
{
public LookupSchoolsConfiguration()
{
Property(l => l.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}
您还可以根据以下帖子将配置直接添加到modelBuilder:https://stackoverflow.com/a/4999894/486028