Entity Framework 6 创建 Id 列,即使定义了其他主键
Entity Framework 6 creates Id column even though other primary key is defined
我将 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.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);
即使主键已设置 Entity Framework 当我 运行 添加迁移时创建一个名为 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);
}
如何防止 EF 添加此列?
查看文档中的文字:
Entity Framework relies on every entity having a key value that it uses for tracking entities. One of the conventions that code first depends on is how it implies which property is the key in each of the code first classes. That convention is to look for a property named “Id” or one that combines the class name and “Id”, such as “BlogId”. The property will map to a primary key column in the database.
要使用不同的密钥,您需要使用注释 [key],例如:
[Key]
public int primaryKey { get; set; }
我怀疑这与您从 EntityData
派生 class 并且 EntityData
有一个名为 Id
的 属性 这一事实有关.我的猜测是 EF 越来越困惑,因为有一个 属性 遵守它的键命名约定(即 Id
)和一个明确定义的键。
我怀疑您必须告诉它明确忽略 Id
。
更新:
我假设您正在为此使用 Azure。 SO question 的答案中包含一些额外信息,可以帮助您找到最佳解决方案。
但是,我同意@Basic 对您问题的评论。由于它们引入的复杂性(和其他问题),我通常回避使用 EF 的复合键。我怀疑对 CompanyId
和 ServiceId
字段的唯一约束将实现您想要的,而无需将它们包含在 SensorType
的主键中。这也意味着您可以只使用派生的 Id
属性 作为您的主键并一起避免整个问题。我不知道你的实现是否可行,但这是需要考虑的事情。
我将 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.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);
即使主键已设置 Entity Framework 当我 运行 添加迁移时创建一个名为 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);
}
如何防止 EF 添加此列?
查看文档中的文字:
Entity Framework relies on every entity having a key value that it uses for tracking entities. One of the conventions that code first depends on is how it implies which property is the key in each of the code first classes. That convention is to look for a property named “Id” or one that combines the class name and “Id”, such as “BlogId”. The property will map to a primary key column in the database.
要使用不同的密钥,您需要使用注释 [key],例如:
[Key]
public int primaryKey { get; set; }
我怀疑这与您从 EntityData
派生 class 并且 EntityData
有一个名为 Id
的 属性 这一事实有关.我的猜测是 EF 越来越困惑,因为有一个 属性 遵守它的键命名约定(即 Id
)和一个明确定义的键。
我怀疑您必须告诉它明确忽略 Id
。
更新:
我假设您正在为此使用 Azure。 SO question 的答案中包含一些额外信息,可以帮助您找到最佳解决方案。
但是,我同意@Basic 对您问题的评论。由于它们引入的复杂性(和其他问题),我通常回避使用 EF 的复合键。我怀疑对 CompanyId
和 ServiceId
字段的唯一约束将实现您想要的,而无需将它们包含在 SensorType
的主键中。这也意味着您可以只使用派生的 Id
属性 作为您的主键并一起避免整个问题。我不知道你的实现是否可行,但这是需要考虑的事情。