CẬP NHẬT: Gần đây tôi đã nhận được một vài sự ủng hộ, vì vậy tôi đoán rằng tôi sẽ cho mọi người biết những lời khuyên tôi đưa ra dưới đây không phải là tốt nhất. Vì ban đầu tôi bắt đầu làm quen với việc thực hiện Entity Framework trên các cơ sở dữ liệu không khóa cũ, tôi đã nhận ra rằng điều tốt nhất bạn có thể làm bởi FAR là làm điều đó bằng cách đảo ngược mã trước. Có một vài bài viết hay về cách làm điều này. Chỉ cần theo dõi họ và sau đó khi bạn muốn thêm khóa vào đó, hãy sử dụng chú thích dữ liệu để "giả" khóa.
Chẳng hạn, giả sử tôi biết bảng của mình Orders
, trong khi nó không có khóa chính, được đảm bảo chỉ có một số thứ tự cho mỗi khách hàng. Vì đó là hai cột đầu tiên trên bảng, nên tôi đã thiết lập mã lớp đầu tiên trông như thế này:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
Bằng cách này, về cơ bản, bạn đã giả mạo EF tin rằng có một cụm được tạo thành từ OrderNumber và Khách hàng. Điều này sẽ cho phép bạn thực hiện chèn, cập nhật, vv trên bảng không cần chìa khóa của bạn.
Nếu bạn không quá quen thuộc với việc thực hiện mã ngược lại trước tiên, hãy đi và tìm một hướng dẫn tốt về Entity Framework Code trước. Sau đó, đi tìm một cái trên Reverse Code First (đang thực hiện Code First với cơ sở dữ liệu hiện có). Sau đó chỉ cần quay lại đây và xem lại lời khuyên chính của tôi. :)
Câu trả lời gốc :
Đầu tiên: như những người khác đã nói, tùy chọn tốt nhất là thêm khóa chính vào bảng. Dấu chấm. Nếu bạn có thể làm điều này, không đọc thêm.
Nhưng nếu bạn không thể, hoặc chỉ ghét chính mình, có một cách để làm điều đó mà không cần khóa chính.
Trong trường hợp của tôi, tôi đã làm việc với một hệ thống cũ (các tệp phẳng ban đầu trên AS400 được chuyển sang Access và sau đó được chuyển sang T-SQL). Thế là tôi phải tìm cách. Đây là giải pháp của tôi. Phần sau đây hoạt động với tôi bằng cách sử dụng Entity Framework 6.0 (mới nhất trên NuGet khi viết bài này).
Nhấp chuột phải vào tệp .edmx của bạn trong Solution Explorer. Chọn "Mở bằng ..." và sau đó chọn "Trình soạn thảo XML (Văn bản)". Chúng tôi sẽ chỉnh sửa bằng tay mã được tạo tự động ở đây.
Hãy tìm một dòng như thế này:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">
Tẩy store:Name="table_name"
từ cuối.
Thay đổi store:Schema="whatever"
thànhSchema="whatever"
Nhìn bên dưới dòng đó và tìm <DefiningQuery>
thẻ. Nó sẽ có một tuyên bố chọn ol 'lớn trong đó. Xóa thẻ và nội dung của nó.
Bây giờ dòng của bạn sẽ trông giống như thế này:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
Chúng tôi có một cái gì đó khác để thay đổi. Đi qua tập tin của bạn và tìm thấy điều này:
<EntityType Name="table_name">
Gần đó có thể bạn sẽ thấy một số văn bản nhận xét cảnh báo bạn rằng nó không có khóa chính được xác định, vì vậy khóa đã được suy ra và định nghĩa là bảng / chế độ chỉ đọc. Bạn có thể để nó hoặc xóa nó. Tôi đã xóa nó.
Dưới đây là <Key>
thẻ. Đây là những gì Entity Framework sẽ sử dụng để thực hiện chèn / cập nhật / xóa. VÌ VẬY, BẠN NÊN LÀM QUYỀN NÀY. Thuộc tính (hoặc thuộc tính) trong thẻ đó cần chỉ ra một hàng có thể nhận dạng duy nhất. Chẳng hạn, giả sử tôi biết bảng của mình orders
, trong khi nó không có khóa chính, được đảm bảo chỉ có một số thứ tự cho mỗi khách hàng.
Vì vậy, của tôi trông như:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
Nghiêm túc, đừng làm điều này sai. Hãy nói rằng mặc dù không bao giờ có sự trùng lặp, nhưng bằng cách nào đó, hai hàng vào hệ thống của tôi có cùng số thứ tự và tên khách hàng. Whooops! Đó là những gì tôi nhận được khi không sử dụng chìa khóa! Vì vậy, tôi sử dụng Entity Framework để xóa một. Bởi vì tôi biết bản sao là thứ tự duy nhất được đưa vào ngày hôm nay, nên tôi làm điều này:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
Đoán xem cái gì? Tôi chỉ xóa cả bản sao VÀ bản gốc! Đó là bởi vì tôi đã nói với Entity Framework rằng order_number / cutomer_name là khóa chính của tôi. Vì vậy, khi tôi nói với nó để loại bỏ trùng lặp, những gì nó đã làm trong nền là một cái gì đó như:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
Và với lời cảnh báo đó ... bây giờ bạn nên đi thật tốt!