Entity framework 具有列序号的实体框架复合键定义<&燃气轮机;主键顺序

Entity framework 具有列序号的实体框架复合键定义<&燃气轮机;主键顺序,entity-framework,ef-code-first,primary-key,code-first,Entity Framework,Ef Code First,Primary Key,Code First,给一张桌子 CREATE TABLE pk_ordinal_test ( C1 INT NOT NULL, C2 INT NOT NULL, C3 INT NOT NULL ) ALTER TABLE pk_ordinal_test ADD PRIMARY KEY (C3, C1); 请注意,主键已定义为C3,C1,列顺序为C1,C3 主键的实体框架代码第一个配置是否应为主键序号: HasKey(x => new { x.C3, x.C1 }); HasKey(x => n

给一张桌子

CREATE TABLE pk_ordinal_test
(
 C1 INT NOT NULL,
 C2 INT NOT NULL,
 C3 INT NOT NULL
)
ALTER TABLE pk_ordinal_test ADD PRIMARY KEY (C3, C1);
请注意,主键已定义为C3,C1,列顺序为C1,C3

主键的实体框架代码第一个配置是否应为主键序号:

HasKey(x => new { x.C3, x.C1 });
HasKey(x => new { x.C1, x.C3 });
或者它应该在第列中:

HasKey(x => new { x.C3, x.C1 });
HasKey(x => new { x.C1, x.C3 });
使用MSI安装中的EF Tools v6.1.3,使用VisualStudio->Add->New item->ADO.Net实体数据模型。首先选择代码,生成以下内容:

public partial class pk_ordinal_test
{
    [Key]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int C1 { get; set; }

    public int C2 { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int C3 { get; set; }
}

上面定义的主键列顺序不正确。

如果有具有复合外键的实体,则必须指定用于相应主键属性的相同列顺序,因此必须选择的选项为主键顺序:

HasKey(x => new { x.C3, x.C1 });

如果在Visual Studio 2015中从数据库生成代码优先模型,它将按照模式中列的顺序为键分配Order属性。因此,如果执行Find之类的LINQ查询,则需要按“列顺序”对主键进行排序,因为键是按模式列顺序排序的

如果要在EDMX中使用数据库优先的方法,则指导原则是在设计器中也使用每个列的主键顺序。因此,如果C1在C3之前,并且都是主键,那么find方法将用作find(C1,C3)

因此,对我来说,有两项证据表明,当使用复合键指定主键顺序时,在代码或设计器中生成模型时,您将使用列顺序,因为代码生成器将使用列顺序对键进行排序

OP的示例(它是我在VS扩展中查询的结果)有点不同,因为模式正在生成主键顺序。让我们退一步,从“嘿,我将从您的模式生成代码优先模型。我看到C1和C3是主键。当我从您的模式生成代码优先模型时,我将按顺序迭代列,并为主键列分配order属性。”这将导致直接基于列顺序的使用模式

同样,OP从一个模式生成一个模型,EF按照每个模式/列的顺序生成代码顺序

将ANSI_空值设置为ON
去
在上设置带引号的\u标识符
去
创建表[dbo]。[UserSetting](
[userId][INT]不为空,
[deleted][BIT]空约束[DF_UserSetting_deleted]默认值((0)),
[key][NVARCHAR](最大值)NULL,
[lastUpdatedUtc][DATETIME2](7)空约束[DF_UserSetting_lastUpdatedUtc]默认值(GETUTCDATE()),
[notificationMessage][NVARCHAR](最大值)NULL,
[notificationType][INT]NULL,
[stringValue][NVARCHAR](最大值)NULL,
[已同步][位]空,
[userSettingId][NCHAR](36)不为空,
[timestamp][DATETIME2](7)空约束[DF_UserSetting_timestamp]默认值(GETUTCDATE()),
[modelVersion][INT]空约束[DF_UserSetting_modelVersion]默认值((0)),
[预览][位]空,
[createdUtc][DATETIME2](7)空约束[DF_UserSetting_createdUtc]默认值(GETUTCDATE()),
约束[PK_UserSetting]主键群集
(
[userSettingId]ASC,
[userId]ASC
)在[主]上打开(PAD\u INDEX=OFF,STATISTICS\u norecocomputer=OFF,IGNORE\u DUP\u KEY=OFF,ALLOW\u ROW\u LOCKS=ON,ALLOW\u PAGE\u LOCKS=ON)
)在[PRIMARY]文本上图像在[PRIMARY]上
去
以下是Visual Studio代码中首先从数据库生成的内容:

[表(“用户设置”)]
公共部分类用户设置
{
[关键]
[第列(顺序=0)]
[数据库生成(DatabaseGeneratedOption.None)]
public int userId{get;set;}
公共bool?已删除{get;set;}
公共字符串密钥{get;set;}
[列(TypeName=“datetime2”)]
公共日期时间?lastUpdatedUtc{get;set;}
公共字符串通知消息{get;set;}
公共int?通知类型{get;set;}
公共字符串stringValue{get;set;}
公共bool?已同步{get;set;}
[关键]
[第列(顺序=1)]
[行政长官(36)]
公共字符串userSettingId{get;set;}
[列(TypeName=“datetime2”)]
公共日期时间?时间戳{get;set;}
公共int?模型版本{get;set;}
公共bool?预览{get;set;}
[列(TypeName=“datetime2”)]
公共日期时间?createdUtc{get;set;}
}

EF不关心数据库中的顺序。它总是按名称而不是顺序引用列。重要的是——整个EF模型的顺序需要一致。如果主键是单向指定的,则引用该主键的外键的顺序必须相同


我首先编写了代码生成器。从数据库中提取信息的组件中有一个“bug”。正如您所发现的,它去掉了组合键中的列顺序。但是,它会保留外键中的哪一列映射到主键中的哪一列。因此,即使它可能无法反映数据库中的布局,生成的模型也能正确地使用数据库。

我认为它也应该如此。但是微软生成器按列顺序(C1,C3)抛出了它,我认为这是一个bug。这很奇怪,你能展示一下你的
ordinal_测试
实体吗?您是在使用Fluent Api配置所有内容,还是也在使用一些数据注释?我不同意Neil的说法:(顺便说一句,我是实体框架反向poco生成器的作者)。我的生成器以主键序号的形式输出,我仍然保持这种方式是正确的。如果允许EF删除并创建数据库,您将需要与最初在SQL中定义的主键序号相同的主键序号。因此正确使用:HasKey(x=>new{x.C3,x.C1})@西蒙休斯我完全理解你的观点,奇怪的是如果