C# 实体框架6创建Id列,即使定义了其他主键
我将DataObject定义为:C# 实体框架6创建Id列,即使定义了其他主键,c#,entity-framework,entity-framework-6,data-annotations,ef-fluent-api,C#,Entity Framework,Entity Framework 6,Data Annotations,Ef Fluent Api,我将DataObject定义为: public class SensorType : EntityData { //PKs public string CompanyId { get; set; } public string ServiceId { get; set; } public string Type { get; set; } } 并使用fluent API将CompanyId和ServiceId设置为复合密钥: modelBuilder.Enti
public class SensorType : EntityData
{
//PKs
public string CompanyId { get; set; }
public string ServiceId { get; set; }
public string Type { get; set; }
}
并使用fluent API将CompanyId和ServiceId设置为复合密钥:
modelBuilder.Entity<SensorType>()
.HasKey(t => new { t.CompanyId, t.ServiceId });
//No autogeneration of PKs
modelBuilder.Entity<SensorType>().Property(t => t.ServiceId)
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
modelBuilder.Entity<SensorType>().Property(t => t.CompanyId)
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
modelBuilder.Entity()
.HasKey(t=>new{t.CompanyId,t.ServiceId});
//不自动生成PKs
modelBuilder.Entity().Property(t=>t.ServiceId)
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
modelBuilder.Entity().Property(t=>t.CompanyId)
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
即使已设置主键,实体框架也会在运行添加迁移时创建名为Id的列:
CreateTable(
"dbo.SensorTypes",
c => new
{
CompanyId = c.String(nullable: false, maxLength: 128),
ServiceId = c.String(nullable: false, maxLength: 128),
Type = c.String(),
Id = c.String(
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "Id")
...
})
.PrimaryKey(t => new { t.CompanyId, t.ServiceId })
.Index(t => t.CreatedAt, clustered: true);
}
CreateTable(
“dbo.SensorTypes”,
c=>新的
{
CompanyId=c.String(可空:false,最大长度:128),
ServiceId=c.String(可空:false,maxLength:128),
Type=c.String(),
Id=c.字符串(
注释:新词典
{
{
“ServiceTableColumn”,
新注释值(旧值:null,新值:“Id”)
...
})
.PrimaryKey(t=>new{t.CompanyId,t.ServiceId})
.Index(t=>t.CreatedAt,聚集:true);
}
如何防止EF添加此列?请参阅文档中的文本: 实体框架依赖于每个实体都有一个用于跟踪实体的键值。代码优先依赖的约定之一是它如何暗示每个代码优先类中哪个属性是键。该约定是查找名为“Id”的属性或将类名和“Id”组合在一起的属性,例如“BlogId”。属性将映射到数据库中的主键列 要使用不同的键,需要使用注释[key],例如:
[Key]
public int primaryKey { get; set; }
我怀疑这与您从
EntityData
派生类,并且EntityData
有一个名为Id
的属性有关。我猜EF会被弄糊涂,因为有一个属性遵循它的关键命名约定(即Id
)和显式定义的键
我怀疑您必须告诉它显式忽略Id
更新:
我假设您正在为此与Azure合作。答案中有一些附加信息,可以帮助您找到最佳解决方案
不过,我同意@Basic对您问题的评论。由于复杂性(以及其他问题),我通常会回避使用EF的复合键它们引入了。我怀疑您的
CompanyId
和ServiceId
字段上的唯一约束将实现您想要的功能,而无需将它们包含在SensorType
的主键中。这也意味着您只需使用派生的Id
属性作为主键,就可以避免整个问题。我不知道你的实现是否可行,但这是一个值得考虑的问题。有意尝试将这两个字段的组合用作复合键。如果是这样,你有一个很好的理由吗?你不需要告诉实体框架关于DigabaseGuangdiod选项。没有,只需设置与公司和服务T的关系即可。在EntityData的代码中,实体数据似乎包含Id,这就是将其作为主数据的原因key@HadiHassan EntityData是一个.NET类。有关它的更多信息,请参阅下面的答案。我认为您不应该从EntityData
类继承,它似乎包含Id属性,或者您可以将其添加到中r fluent api,modelBuilder.Entity().Ignore(t=>t.Id)
现在情况清楚了,EntityData中的Id也生成为Id,他可以告诉fluent api忽略它,或者干脆不让SensorType从EntityDataIgnoring Id继承!但是这违反了Libskovs替换原则。是否可以使用EF并让它在不继承Enti的情况下生成控制器tyData?它提供:CreatedAt、UpdatedAt等,当然还有Id。