I'm working on a Core MVC project that reads data (no writing required) from a pre-existing database. Unfortunately this database is a total mess, but I cannot change anything in it (and even if I could, I wouldn't touch it with a 10-foot pole).
Some of the relevant problems of the database are the following:
Nevertheless I am forced to read data from this database and would prefer to use Entity Framework to do so.
The database is hosted in SQL Server 2008R2.
I could make it work with no issue on one of the tables I have to use, by using attributes such as [Table], [Column] and [Key] to use a class with proper property names mapped to the real column names. Another table however is proving to be a problem.
This table doesn't have a single column that could be considered a primary key, but I found that a combination of two columns is unique for each row, so they could be considered a composite primary key (even if they're not defined as such in the database).
I've defined a class like the following (I've changed the names to hide the identity of this database, as much as I'd like to name and shame):
[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; }
}
Still, trying to run the project produces an error:
InvalidOperationException: The entity type 'MyProject.Models.Order' requires a primary key to be defined.
Is there anything more I can add to make this table work with Entity Framework?
EDIT: I discovered it works if I define it in the context's OnModelCreating
method, like modelBuilder.Entity<Order>().HasKey(ord => new { ord.OrderNo, ord.OrderLineNo });
. However I'd still prefer to do it with attributes alone, if possible.
Your configuration works fine with EF6. But you must be careful when using Data Annotations with EF Core (looks like Fluent API will be the preferred approach there).
The Keys(primary) section of the documentation explicitly states:
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.
So you really need to use:
modelBuilder.Entity<Order>().HasKey(e => new { e.OrderNo, e.OrderLineNo });