我有一个基本实体类,我希望能够继承它,这样我只需要为许多不同的特定于实体的存储库编写1 GetById
方法。然而," Id"我的一些数据库表中的列必须被调用" Code"由于遗产原因。
我试过(简化版):
public class EntityBase{
int Id;
}
public class IdEntity : EntityBase{
}
public class CodeEntity : EntityBase{
}
然后在DbContext中:
modelBuilder.Entity<IdEntity>(entity =>
{
entity.HasKey(e=>e.Id).HasName("PK_IdEntity");
entity.Property(e=>e.Id).HasColumnName("ID");
}
modelBuilder.Entity<CodeEntity>(entity =>
{
entity.HasKey(e=>e.Id).HasName("PK_CodeEntity");
entity.Property(e=>e.Id).HasColumnName("Code"); //this seems to be where it breaks
}
这构建很好,但是当我尝试运行它时,我得到一个InvalidOperationException: 无法为房产调用房产&#39; Id&#39;在实体类型&#39; CodeEntity&#39;因为它被配置为导航属性。属性只能用于配置标量属性。
我试图做的不可能吗?这对我来说似乎不太可能,但那么这样做的正确方法是什么?
我实际上试图做的事情比简化的&#34;更复杂。代码我发布在这里。我想这样做,所以我可以有一个字符串或int ID,并使用相同的GetById
方法。所以我创建了一个对string和int进行隐式转换的类,我认为这对于Entity Framework是可以的。
不是。
运行时错误是由于尝试告诉EF具有EntityID
类型的属性应该是我的密钥,而您不允许这样做。
我无法从Microsoft找到有关Entity Framework中关键值要求的任何文档,但我发现另一个SO问题,即只允许使用标量和字节[] Type safe keys with Entity Framework model
答案 0 :(得分:1)
我无法获得上面的代码来编译或提供异常,因为在尝试修复它之后你已经足够了。虽然我将描述如何编写您想要实现的场景。
如果要在EF中使用EntityBase
作为PK属性,则需要将其设为公共属性。在您的代码中,它是一个私有字段(因为没有get / set方法)。所以你的public class EntityBase
{
public int Id { get; set; }
}
类看起来应该是这样的
OnModelCreating
通过以上更改和GetById
代码来映射有问题的实体类型,模型构建正常地创建具有所需表结构和名称的表。
以下是在dbset上实现通用public static T GetById<T>(DbSet<T> dbset, int id)
where T : EntityBase
{
return dbset.FirstOrDefault(e => e.Id == id);
}
// example
var entity = GetById(db.Set<IdEntity>(), 2);
的小方法。它可以成为通用存储库甚至扩展方法的一部分。
inputs