我将DataObject定义为:
public class SensorType : EntityData
{
//PKs
public string CompanyId { get; set; }
public string ServiceId { get; set; }
public string Type { get; set; }
}
使用流畅的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);
即使设置了主键,当我运行Add-Migration时,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添加此列?
答案 0 :(得分:2)
我怀疑这与您从EntityData
派生班级的事实有关,EntityData
有一个名为Id
的媒体资源。我猜测EF很混乱,因为有一个属性符合它的关键命名约定(即Id
)和明确定义的键。
我怀疑你必须告诉它明确忽略Id
。
<强>更新强>
我假设您正在与Azure合作。这个SO question在答案中有一些额外的信息,可以帮助您找到最佳解决方案。
但是,我同意@Basic对你的问题的评论。由于它们引入的复杂性(和其他问题),我通常回避使用EF的复合键。我怀疑CompanyId
和ServiceId
字段的唯一约束将达到您想要的效果,而不会将它们包含在SensorType
的主键中。这也意味着您可以使用派生的Id
属性作为主键,并避免整个问题。我不知道你的实现是否可行,但需要考虑。
答案 1 :(得分:-1)
参见文档中的文字:
实体框架依赖于具有用于跟踪实体的密钥值的每个实体。代码首先依赖的约定之一是它如何暗示哪个属性是每个代码第一类中的键。该惯例是查找名为“Id”的属性或组合类名称和“Id”的属性,例如“BlogId”。该属性将映射到数据库中的主键列。
要使用其他密钥,您需要使用注释[key],例如:
[Key]
public int primaryKey { get; set; }