我应该如何为现有数据库 table 定义复合主键?
How should I define a composite primary key for an existing database table?
我正在开发一个从预先存在的数据库中读取数据(无需写入)的 Core MVC 项目。不幸的是,这个数据库一团糟,但我无法更改其中的任何内容(即使我可以,我也不会用 10 英尺长的杆子碰它)。
数据库的一些相关问题如下:
- table彼此之间没有任何外键关系,并且包含最好输入到子table中的数据;创建该数据库的人似乎将 table 用作 Excel 电子表格。
- 没有定义主键或外键。
- table 的名称和列似乎是所包含数据的首字母(举个假想的例子,通常命名为 "Customer" 的 table 应该是"dbbc" "Database - Business Customer").
- table 不在 "dbo" 架构中。
尽管如此,我不得不从这个数据库中读取数据,并且更愿意使用 Entity Framework 来这样做。
数据库托管在SQL Server 2008R2。
通过使用 [Table]、[Column] 和 [Key] 等属性,我可以使它在我必须使用的 table 之一上正常工作a class 具有正确的 属性 名称映射到真实的列名称。然而,另一个 table 被证明是一个问题。
这个 table 没有一个列可以被认为是主键,但我发现两列的组合 是 每一行唯一的, 因此它们可以被视为复合主键(即使它们在数据库中未定义为复合主键)。
我已经定义了一个 class 如下(我已经更改了名称以隐藏该数据库的身份,尽管我想命名和羞辱):
[Table("dbbo", Schema = "schema")]
public class Order
{
[Key]
[Column("order", Order = 0)]
public string OrderNo { get; set; }
[Key]
[Column("order_line", Order = 1)]
public string OrderLineNo { get; set; }
[Column("qty")]
public double Quantity { get; set; }
[Column("pr")]
public double Price { get; set; }
}
- 我已将 [Key] 属性添加到构成假想复合主键的两列。
- 我已经为 [Column] 属性的 Order 属性 添加了一个值,因为我读到它是复合键所必需的。
- 我只映射了我需要使用的列,因为 table 的列比与此项目相关的列多了大约 10 倍。
仍然,尝试 运行 项目会产生错误:
InvalidOperationException: The entity type 'MyProject.Models.Order' requires a primary key to be defined.
还有什么我可以添加来使这个 table 与 Entity Framework 一起工作吗?
编辑: 我发现如果我在上下文的 OnModelCreating
方法中定义它,它会起作用,比如 modelBuilder.Entity<Order>().HasKey(ord => new { ord.OrderNo, ord.OrderLineNo });
。但是,如果可能的话,我仍然更喜欢单独使用属性。
您的配置适用于 EF6。但是在 EF Core 中使用数据注释时必须小心(看起来 Fluent API 将是那里的首选方法)。
文档的 Keys(primary) 部分明确指出:
You can also use the Fluent API to configure multiple properties to be the key of an entity (known as a composite key). Composite keys can only be configured using the Fluent API - conventions will never setup a composite key and you can not use Data Annotations to configure one.
所以你真的需要使用:
modelBuilder.Entity<Order>().HasKey(e => new { e.OrderNo, e.OrderLineNo });
我正在开发一个从预先存在的数据库中读取数据(无需写入)的 Core MVC 项目。不幸的是,这个数据库一团糟,但我无法更改其中的任何内容(即使我可以,我也不会用 10 英尺长的杆子碰它)。
数据库的一些相关问题如下:
- table彼此之间没有任何外键关系,并且包含最好输入到子table中的数据;创建该数据库的人似乎将 table 用作 Excel 电子表格。
- 没有定义主键或外键。
- table 的名称和列似乎是所包含数据的首字母(举个假想的例子,通常命名为 "Customer" 的 table 应该是"dbbc" "Database - Business Customer").
- table 不在 "dbo" 架构中。
尽管如此,我不得不从这个数据库中读取数据,并且更愿意使用 Entity Framework 来这样做。
数据库托管在SQL Server 2008R2。
通过使用 [Table]、[Column] 和 [Key] 等属性,我可以使它在我必须使用的 table 之一上正常工作a class 具有正确的 属性 名称映射到真实的列名称。然而,另一个 table 被证明是一个问题。
这个 table 没有一个列可以被认为是主键,但我发现两列的组合 是 每一行唯一的, 因此它们可以被视为复合主键(即使它们在数据库中未定义为复合主键)。
我已经定义了一个 class 如下(我已经更改了名称以隐藏该数据库的身份,尽管我想命名和羞辱):
[Table("dbbo", Schema = "schema")]
public class Order
{
[Key]
[Column("order", Order = 0)]
public string OrderNo { get; set; }
[Key]
[Column("order_line", Order = 1)]
public string OrderLineNo { get; set; }
[Column("qty")]
public double Quantity { get; set; }
[Column("pr")]
public double Price { get; set; }
}
- 我已将 [Key] 属性添加到构成假想复合主键的两列。
- 我已经为 [Column] 属性的 Order 属性 添加了一个值,因为我读到它是复合键所必需的。
- 我只映射了我需要使用的列,因为 table 的列比与此项目相关的列多了大约 10 倍。
仍然,尝试 运行 项目会产生错误:
InvalidOperationException: The entity type 'MyProject.Models.Order' requires a primary key to be defined.
还有什么我可以添加来使这个 table 与 Entity Framework 一起工作吗?
编辑: 我发现如果我在上下文的 OnModelCreating
方法中定义它,它会起作用,比如 modelBuilder.Entity<Order>().HasKey(ord => new { ord.OrderNo, ord.OrderLineNo });
。但是,如果可能的话,我仍然更喜欢单独使用属性。
您的配置适用于 EF6。但是在 EF Core 中使用数据注释时必须小心(看起来 Fluent API 将是那里的首选方法)。
文档的 Keys(primary) 部分明确指出:
You can also use the Fluent API to configure multiple properties to be the key of an entity (known as a composite key). Composite keys can only be configured using the Fluent API - conventions will never setup a composite key and you can not use Data Annotations to configure one.
所以你真的需要使用:
modelBuilder.Entity<Order>().HasKey(e => new { e.OrderNo, e.OrderLineNo });