如何在Entity Framework代码第一个数据库中手动设置实体主键?

Dmy*_*tro 6 c# entity-framework primary-key

好吧,我有以下模型结构:我有一个类 - DatabaseEntity基本上

public class DatabaseEntity
{
    public int Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

所以像产品,类别等每个实体都会继承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();
}
Run Code Online (Sandbox Code Playgroud)

然后我从eBay下载eBay api列表中的categoies我必须添加到数据库中.基本上类别是:

public class EbayCategory : DatabaseEntity
{
    // It has Id since it inherits DatabaseEntity
    public string Name { get; set; }      
    // ... some other properties
}
Run Code Online (Sandbox Code Playgroud)

但问题是,当我下载这些类别时,我下载了他们的Id属性,当然,这些属性已经有了价值.当我尝试将它们保存到数据库时:

public void UpdateCategories(IEnumerable<EbayCategory> newCategories)
{
    foreach (var newCategory in newCategories)
    {
        _repository.InsertOrUpdate(newCategory);
    }
}
Run Code Online (Sandbox Code Playgroud)

我面临一些问题...首先,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."
Run Code Online (Sandbox Code Playgroud)

...因为它认为其他人删除了我想要更新的实体.如何保存此InsertOrUpdate逻辑,因为许多项目都基于它,并且能够将EbayCategories带有主键(Id)的items()添加到数据库,然后像其他实体一样更新/删除它们而不丢弃EbayCategory.Id值?

Col*_*lin 10

要允许您手动生成ID,您需要一个具有手动生成ID的类 - 因此它无法继承 DatabaseEntity

public class EbayCategory
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }

    public string Name { get; set; }      
    // ... some other properties
}
Run Code Online (Sandbox Code Playgroud)

现在,您将需要一个不同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();
}
Run Code Online (Sandbox Code Playgroud)