实体框架6创建Id列,即使定义了其他主键

本文关键字:定义 其他 框架 创建 Id 实体 | 更新日期: 2023-09-27 18:07:45

我将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);

即使设置了主键,当我运行AddMigration:时,实体框架也会创建一个名为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添加此列?

实体框架6创建Id列,即使定义了其他主键

我怀疑这与您从EntityData派生类的事实有关,而EntityData有一个名为Id的属性。我的猜测是,EF变得很困惑,因为有一个属性符合它的密钥命名约定(即Id(和一个明确定义的密钥。

我怀疑您必须告诉它显式忽略Id

MSDN:EntityData类

更新:

我假设你正在与Azure合作。这个SO问题的答案中有一些额外的信息,可以帮助您找到最佳解决方案。

不过,我同意@Basic对您问题的评论。由于EF的复杂性(以及其他问题(,我通常会回避使用它们的复合密钥。我怀疑CompanyIdServiceId字段上的唯一约束将在不将它们包含在SensorType的主键中的情况下实现您想要的。这也意味着您只需使用派生的Id属性作为主键,就可以避免整个问题。我不知道这对你的实施是否可行,但这是需要考虑的。

请参阅文档中的文本:

实体框架依赖于每个实体都有一个用于跟踪实体的键值。代码首先依赖的约定之一是它如何暗示哪个属性是每个代码优先类中的键。这种约定是寻找一个名为"Id"的属性,或者一个将类名和"Id"组合在一起的属性,例如"BlogId"。该属性将映射到数据库中的主键列。

要使用不同的密钥,您需要使用注释[key],例如:

[Key] 
public int primaryKey { get; set; } 

官方文件

教程链接