13

Đây là tình huống của tôi: Tôi đã làm việc trên ứng dụng ASP.NET MVC 3 trong một thời gian. Nó có một cơ sở dữ liệu (được xây dựng từ một dự án db; tôi sẽ sử dụng db-first) mà tôi có một mô hình edmx và sau đó là một tập các POCO. Các thực thể của tôi có tên số nhiều trong cơ sở dữ liệu và các POCO có tên ít. Tất cả mọi thứ bản đồ độc đáo mà không có một vấn đề.Entity Framework (4.3) tìm kiếm tên số ít thay vì số nhiều (khi tên thực thể kết thúc bằng "s")

Hoặc được sử dụng cho đến khi tôi thêm một bảng mới (được gọi là TransactionStatuses). Bây giờ tất cả các thực thể cũ vẫn hoạt động nhưng thực thể mới thì không. Khi tôi cố gắng hăm hở nạp nó cùng với một thực thể có liên quan:

var transactions = (from t in db.Transactions.Include(s => s.TransactionStatus) //TransactionStatus - navigation property in Transactions to TransactionStatuses 
        where t.CustomerID == CustomerID 
        select t).ToList(); 

tôi nhận được

tên đối tượng không hợp lệ 'dbo.TransactionStatus'.

Tôi thậm chí đã làm một thử nghiệm đơn giản:

List<TransactionStatus> statuses = db.TransactionStatuses.ToList(); 

= cùng một kết quả.

Tôi đã cập nhật (và thậm chí được tạo lại) edmx từ db và đã trải qua nó qua lại cố gắng tìm ra những điểm khác biệt về ánh xạ cho dbo.TransactionStatus * es * lên.

Nếu ai đó có thể chỉ cho tôi theo hướng sửa chữa thì điều đó thật tuyệt vời.

P.S. Tắt đa nguyên không phải là một lựa chọn, cảm ơn.

Cập nhật: Tôi đã tìm ra câu trả lời của tôi bên dưới.

+0

bạn có thể tạo phiên bản mới của TransactionStatuses không? Nếu vậy hãy nhìn vào sql ra ngoài mà EF đang tạo ra và chắc chắn rằng nó đang chỉ rõ bảng chính xác. – BentOnCoding

+0

Đó là vấn đề, SQL có tên số ít ... và tôi đang cố gắng tìm ra lý do và cách khắc phục. –

Trả lời

31

Điều này có thể xảy ra vì mặc dù ý định là sử dụng luồng Cơ sở dữ liệu thứ nhất, thực tế là ứng dụng đang sử dụng Mã đầu tiên để thực hiện ánh xạ. Hãy để tôi giải thích thêm một chút vì điều này có thể gây nhầm lẫn. :-)

Khi sử dụng Cơ sở dữ liệu Đầu tiên với EF Designer và các mẫu DbContext trong Visual Studio, ba điều rất quan trọng xảy ra. Đầu tiên, trình thủ thuật Mô hình dữ liệu thực thể mới thêm chuỗi kết nối vào ứng dụng của bạn chứa các chi tiết của mô hình Cơ sở dữ liệu đầu tiên (tức là EDMX) để khi ứng dụng chạy nó có thể tìm thấy mô hình này. Chuỗi kết nối sẽ giống như thế này:

<connectionStrings> 
    <add name="MyEntities" 
    connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.\sqlexpress;initial catalog=MyEntities;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;" 
    providerName="System.Data.EntityClient" /> 
</connectionStrings> 

Thứ hai, lớp bối cảnh tạo thực hiện cuộc gọi đến các cơ sở DbContext constructor chỉ định tên của chuỗi kết nối này:

public MyEntities() 
: base("name=MyEntities") 
{ 
} 

này cho DbContext để tìm và sử dụng chuỗi kết nối "MyEntities" trong cấu hình. Sử dụng "name =" có nghĩa là DbContext sẽ ném nếu nó không tìm thấy chuỗi kết nối - nó sẽ không chỉ đi trước và tạo kết nối theo quy ước.

Nếu bạn muốn sử dụng Cơ sở dữ liệu đầu tiên, thì bạn phải sử dụng chuỗi kết nối giống như chuỗi được tạo. Cụ thể, nó phải chứa dữ liệu mô hình (csdl, msl, ssdl từ EDMX) và bạn phải chắc chắn rằng DbContext tìm thấy nó. Hãy rất cẩn thận khi thay đổi cuộc gọi đến hàm tạo cơ sở.

Điều thứ ba xảy ra là OnModelCreating sẽ bị thay thế trong bối cảnh được tạo ra và thực hiện để ném:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    throw new UnintentionalCodeFirstException(); 
} 

này được thực hiện vì OnModelCreating chỉ bao giờ gọi khi sử dụng Mã đầu tiên. Điều này là do OnModelCreating là tất cả về việc tạo mô hình, nhưng khi bạn đang sử dụng Database Trước tiên, mô hình đã tồn tại - không có gì để tạo ra khi chạy. Vì vậy, nếu OnModelCreating được gọi thì có thể là vì bạn đã bắt đầu sử dụng Code First mà không có ý nghĩa, thường là do sự thay đổi đối với chuỗi kết nối hoặc lệnh gọi hàm tạo cơ sở.

Bây giờ, có thể bạn muốn sử dụng Code First để ánh xạ tới cơ sở dữ liệu hiện có. Đây là một mô hình tuyệt vời và được hỗ trợ đầy đủ (xem http://blogs.msdn.com/b/adonet/archive/2011/03/07/when-is-code-first-not-code-first.aspx) nhưng bạn sẽ cần phải đảm bảo ánh xạ được thiết lập phù hợp để làm việc này. Nếu ánh xạ không được thiết lập đúng thì bạn sẽ nhận được các ngoại lệ giống như câu hỏi trong câu hỏi này.

+0

OK Tôi hiểu rồi! điều này là tuyệt vời, tôi sẽ quay trở lại để kiểm tra các bước này nhưng tôi nghĩ rằng tôi thiếu tham chiếu để sửa chuỗi kết nối trong DbContext constructor! Điều đó có nghĩa là nó đang xảy ra mã đầu tiên. Tôi sẽ cập nhật những phát hiện của tôi. –

+1

Vâng, điều này chắc chắn là nó. Tôi đã có chuỗi kết nối chính xác trong dự án DAL của tôi nhưng không phải trong dự án ứng dụng MVC của tôi (nơi tôi đã có một chuỗi kết nối thông thường). Tôi đã cố gắng thay đổi điều này theo các điểm mà bạn nêu ra nhưng tôi bắt đầu nhận được UnintentionalCodeFirstException và tôi không thể hiểu được điều gì đang gọi nó ... tóm lại, cảm ơn bạn rất nhiều vì đã làm rõ điều này. Đây là lần đầu tiên tôi nhìn thấy một sự phân biệt rõ ràng về việc thiết lập giữa Code First và DB trước tiên. –

0

Bạn đề cập đến EDMX nhưng tôi không thể biết liệu bạn có đang làm databse đầu tiên với EDMX hay mã đầu tiên và chỉ sử dụng EDMX để xem điều gì đang diễn ra.

Nếu bạn đang sử dụng Mã đầu tiên, thì bạn có thể sử dụng cấu hình để chỉ định tên bảng. Chú thích dữ liệu là [Bảng ("TransactionStatuses")], thông thạo là modelBuilder.Entity(). ToTable ("TransactionStatuses"). (Tôi đang nhập chú thích và mã thông thạo từ bộ nhớ để kiểm tra tham chiếu kép.))

Nếu trước tiên bạn sử dụng cơ sở dữ liệu, SSDL phải biết tên bảng cơ sở dữ liệu đoán rằng bạn đang sử dụng mã đầu tiên & bản edmx chỉ dành cho việc khám phá. (???)

hth

+0

Xin lỗi vì không rõ ràng, tôi sẽ dùng db-first. Trong tất cả mọi thứ edmx trông ok với đặt tên nhưng khi nói đến thời gian chạy ... –

7

OK! Horrible, horrible kinh nghiệm ...

Nói tóm lại: EF không thể pluralize đúng tên thực thể kết thúc bằng "s" (ví dụ như "trạng thái", "trường", vv)

Đây là cách tôi có nó và bằng chứng.

  • Tôi đã tạo và tạo lại thiết lập ban đầu của mình nhiều lần với cùng một kết quả.
  • Tôi cũng đã thử đổi tên bảng của mình thành những thứ như TransStatus và các nội dung tương tự - không may mắn.
  • Khi tôi đang nghiên cứu về điều này, tôi đã xem qua số pluralization article by Scott Hanselman nơi ông đã thêm quy tắc số nhiều cho các từ như sheepgoose. Điều này khiến tôi suy nghĩ "nếu vấn đề của anh ấy nằm trong tên thực tế của thực thể?"
  • Tôi đã thực hiện một số tìm kiếm về từ status nói riêng và được tìm thấy this report of the problem on Connect. Tôi vội vàng thử đổi tên đối tượng của mình ...
  • Đổi tên TransactionStatuses thành TransactionStates (trong khi vẫn giữ các cột là StatusID) khắc phục sự cố! Tôi có thể nhận được List<TransactionState> statuses = db.TransactionStates.ToList();
  • Tôi nghĩ rằng vấn đề là với từ cụ thể status trong tên ... Nhưng sau khi than phiền về điều này với một người bạn, tôi đã đề xuất rằng có thể vấn đề là với từ kết thúc bằng "s". .. Vì vậy, tôi quyết định kiểm tra xem nó ra.
  • Tôi thiết lập một bảng khác có tên là Campuses và khớp với POCO Campus (và cập nhật edmx). Đã làm thử nghiệm đơn giản List<Campus> test = db.Campuses.ToList(); và nhận ngay bây giờ mong đợi

Tên đối tượng không hợp lệ 'dbo.Campus'.

Vì vậy, có bạn đi, EF hùng mạnh không thể xử lý số nhiều từ kết thúc bằng "s". Hy vọng rằng, bugger nghèo tiếp theo đánh vào vấn đề sẽ tìm ra câu hỏi này và tự cứu mình 3-4 giờ đau đớn và thất vọng.

+4

EF không sử dụng dịch vụ số nhiều của nó để đặt tên cho cơ sở dữ liệu. Nó chỉ sử dụng nó để đặt tên thực thể trong mô hình trở thành bộ đối tượng (hoặc dbset) trong lớp ngữ cảnh của bạn. Nếu bạn làm cơ sở dữ liệu đầu tiên, EF biết tên của bảng của bạn bởi vì nó nhận được thông tin directl từ cơ sở dữ liệu. Trong EDMX theo mặc định, nó sẽ làm công việc tốt nhất của bạn để tạo ra một tên thực thể số nhiều từ thực thể. Nhưng sau đó là tệp ánh xạ cho biết rằng thực thể đó ánh xạ tới bất kỳ tên bảng nào mà nó thấy trong db cơ sở khi bạn tạo mô hình –

+1

và dịch vụ số nhiều chắc chắn bị giới hạn. Tôi đồng ý về điều đó. Nhưng tôi không hiểu làm thế nào mà có bất cứ điều gì để làm với tên bảng cơ sở dữ liệu. –

+0

Tôi biết điều đó, cảm ơn. Và như tôi đã nói trong EDMX mọi thứ đều ổn, ví dụ: tên bảng "xStatuses" và lớp phù hợp "xStatus". Nhưng khi nó tạo ra SQL, nó sẽ tìm "dbo.xStatus" trong db mặc dù _it đọc ra khỏi db thành edmx_ rằng tên bảng là "xStatuses". Hãy thử ví dụ về trường tôi đã đưa ra và bạn sẽ thấy nó xảy ra. –

0

Thở dài. Cùng loại vấn đề với lớp và mô hình Ảnh và Video; nó đang tìm kiếm các Photoes và Videoes. Tôi ghét chỉ thay đổi tên bảng, nhưng không có nhiều lựa chọn.

Các vấn đề liên quan