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);
}
}