C# 如何在实体框架代码优先数据库中手动设置实体主键?

C# 如何在实体框架代码优先数据库中手动设置实体主键?,c#,entity-framework,primary-key,C#,Entity Framework,Primary Key,我有以下模型结构:我有一个类-DatabaseEntity,它基本上是 public class DatabaseEntity { public int Id { get; set; } } 因此,每个实体(如产品、类别等)都将继承DatabaseEntity,并具有Id属性。我还有典型的EntityFrameworkrepository类和InsertOrUpdate方法: private readonly DbContext _database; public void Inse

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

public class DatabaseEntity
{
    public int Id { get; set; }
}
因此,每个实体(如产品、类别等)都将继承
DatabaseEntity
,并具有
Id
属性。我还有典型的
EntityFramework
repository类和
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();
}
但是,问题是,当我下载我下载的类别和它们的Id属性时,它们当然已经有了值。当我尝试将它们保存到数据库时,如:

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

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

要允许手动生成Id,您需要一个具有手动生成Id的类-因此它不能从
数据库实体继承

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();
}
public void InsertOrUpdate(EbayCategory实体)
{
if(Find(entity.ID==null)
{
//新实体
DbSet().Add(实体);
}
其他的
{
//现有实体
_database.Entry(entity).State=EntityState.Modified;
}
_SaveChanges();
}

科林上面的回答非常正确地展示了如何使用数据注释实现此设置。 但是在所提出的问题中,实体是一个子类,因此在不更改实体类的情况下无法添加注释

还有另一种配置方法:Fluent配置。下面是我使用EntityTypeConfiguration类的示例:

public class LookupSchoolsConfiguration : EntityTypeConfiguration<LookupSchools>
    {
        public LookupSchoolsConfiguration()
        {
            Property(l => l.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        }
    }
公共类LookupSchoolConfiguration:EntityTypeConfiguration
{
public LookupSchoolsConfiguration()
{
属性(l=>l.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}

您也可以根据以下帖子直接向modelBuilder添加配置:

您需要Id值吗?为什么不放弃它,让sql server通过Identity生成一个新Id?@RosdiKasim,是的,我需要该Id值。其他类的Id情况如何?如果不修改
InsertOrUpd,我看不到任何方法可以做到这一点ate
方法。您可以更改方法以首先签入数据库,如按id查询,如果项目在那里,则更新,否则插入。但是,如果项目很多,这可能会很昂贵。
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();
}
public class LookupSchoolsConfiguration : EntityTypeConfiguration<LookupSchools>
    {
        public LookupSchoolsConfiguration()
        {
            Property(l => l.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        }
    }