2008-09-17 37 views
21

Tôi đang gặp khó khăn khi cố gắng gỡ lỗi LINQ to SQL và gửi các thay đổi.Gỡ lỗi LINQ to SQL SubmitChanges()

Tôi đã sử dụng http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx, hoạt động tuyệt vời để gỡ lỗi các truy vấn đơn giản.

Tôi đang làm việc trong lớp DataContext cho dự án của tôi với đoạn sau đây từ ứng dụng của tôi:

JobMaster newJobToCreate = new JobMaster(); 
newJobToCreate.JobID = 9999 
newJobToCreate.ProjectID = "New Project"; 
this.UpdateJobMaster(newJobToCreate); 
this.SubmitChanges(); 

tôi sẽ bắt một số trường hợp ngoại lệ rất kỳ quặc khi tôi chạy this.SubmitChanges;

Index was outside the bounds of the array. 

Các vết đống đi những nơi tôi không thể bước vào:

at System.Data.Linq.IdentityManager.StandardIdentityManager.MultiKeyManager`3.TryCreateKeyFromValues(Object[] values, MultiKey`2& k) 
    at System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache`2.Find(Object[] keyValues) 
    at System.Data.Linq.IdentityManager.StandardIdentityManager.Find(MetaType type, Object[] keyValues) 
    at System.Data.Linq.CommonDataServices.GetCachedObject(MetaType type, Object[] keyValues) 
    at System.Data.Linq.ChangeProcessor.GetOtherItem(MetaAssociation assoc, Object instance) 
    at System.Data.Linq.ChangeProcessor.BuildEdgeMaps() 
    at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
    at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 
    at System.Data.Linq.DataContext.SubmitChanges() 
    at JobTrakDataContext.CreateNewJob(NewJob job, String userName) in D:\JobTrakDataContext.cs:line 1119 

Có ai có bất kỳ công cụ hay kỹ thuật mà họ sử dụng không? Tôi thiếu một cái gì đó đơn giản?

EDIT: tôi đã thiết lập .net debugging sử dụng gợi ý Slace, tuy nhiên mã .net 3.5 là chưa có sẵn: http://referencesource.microsoft.com/netframework.aspx

EDIT2: Tôi đã thay đổi để InsertOnSubmit theo của sirrocco gợi ý, vẫn nhận được lỗi tương tự.

EDIT3: Tôi đã triển khai các đề xuất của Sam đang cố gắng ghi nhật ký SQL được tạo và nắm bắt được ChangeExceptoinException. Những gợi ý này không làm sáng tỏ thêm chút nào, tôi chưa bao giờ thực sự tạo ra SQL khi ngoại lệ của tôi bị ném ra.

EDIT4: Tôi tìm thấy câu trả lời phù hợp với tôi bên dưới. Nó chỉ là một lý thuyết nhưng nó đã cố định vấn đề hiện tại của tôi.

+0

Lỗi này xảy ra với nhiều khách hàng, chỉ trên máy có Windows XP, tôi tìm thấy bản sửa lỗi nóng này đã giải quyết được sự cố. [i386] (http://hotfixv4.microsoft.com/.NET%20Framework%203.5%20-%20Windows%20Server%202003,%20WindowsXP,%20Windows%20Vista,%20Windows%20Server%202008%20 (MSI)/sp1/DevDiv975687/30729.5821/miễn phí/448814_intl_i386_zip.exe) và [x64] (http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=963657&kbln=en-us) – gpiccin

Trả lời

8

Đầu tiên, cảm ơn tất cả mọi người đã được giúp đỡ, cuối cùng tôi đã tìm thấy nó.

Giải pháp là để thả tệp .dbml từ dự án, thêm tệp .dbml trống và repopulate nó với các bảng cần thiết cho dự án của tôi từ 'Server Explorer'.

tôi nhận thấy một vài điều trong khi tôi đang làm điều này:

  • Có một vài bảng trong hệ thống tên với hai chữ và một không gian ở giữa các từ, ví dụ: 'Job Thạc sĩ'. Khi tôi kéo bảng đó trở lại tệp .dbml, nó sẽ tạo ra một bảng có tên là 'Job_Master', nó sẽ thay thế không gian bằng dấu gạch dưới.
  • Trong tệp .dbml gốc, một trong các nhà phát triển của tôi đã trải qua tệp .dbml và xóa tất cả dấu gạch dưới, do đó 'Job_Master' sẽ trở thành 'JobMaster' trong tệp .dbml. Trong mã, chúng ta có thể tham khảo bảng trong một quy ước đặt tên tiêu chuẩn hơn cho chúng ta.
  • Lý thuyết của tôi là ở đâu đó, bản dịch từ 'JobMaster' thành 'Job Master' trong khi bị mất trong khi thực hiện phép chiếu, và tôi tiếp tục đưa ra lỗi ngoài giới hạn.

Nó chỉ là một lý thuyết. Nếu ai đó có thể giải thích rõ hơn thì tôi rất thích có một câu trả lời cụ thể ở đây.

+2

Ai đó đã tạo ra một liên kết từ một thực thể này đến một thực thể khác, ở đó đầu bên ngoài không phải là khóa chính. Đây là lỗi trong 3.5 SP1. – DamienG

1

Một giải pháp đơn giản có thể là chạy một dấu vết trên cơ sở dữ liệu của bạn và kiểm tra các truy vấn chạy ngược lại - lọc ofcourse để phân loại các ứng dụng khác, vv truy cập cơ sở dữ liệu.

Điều đó ofcourse chỉ giúp một khi bạn vượt qua các ngoại lệ ...

0

Hrm.

Lấy một WAG (Wild Ass Guess), có vẻ như tôi thích LINQ - SQL đang cố tìm một đối tượng có id không tồn tại, dựa trên cách nào đó để tạo lớp JobMaster. Có các khóa ngoại có liên quan đến bảng đó để LINQ to SQL có thể tìm nạp một cá thể của một lớp, có thể không tồn tại? Dường như bạn đang thiết lập ProjectID của đối tượng mới thành một chuỗi - bạn có thực sự có một id là một chuỗi không? Nếu bạn đang cố gắng đặt nó vào một dự án mới, bạn sẽ cần phải tạo một dự án mới và lấy id của nó.

Cuối cùng, UpdateJobMaster làm gì? Nó có thể làm một cái gì đó như vậy mà ở trên sẽ được áp dụng?

1

VS 2008 có khả năng gỡ lỗi mặc dù.NET framework (http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx)

Đây có lẽ là lựa chọn tốt nhất của bạn, bạn có thể xem những gì đang xảy ra và những gì tất cả các thuộc tính là tại thời điểm chính xác trong thời gian

+0

Kể từ hôm nay http: // referencesource .microsoft.com/netframework.aspx mã nguồn cho .net 3.5 chưa khả dụng. – ben

2

Các lỗi mà bạn đang đề cập đến ở trên thường được gây ra bởi các liên kết trỏ sai hướng. Điều này xảy ra rất dễ dàng khi thêm các liên kết vào trình thiết kế theo cách thủ công vì các mũi tên liên kết trong điểm thiết kế L2S ngược lại khi so sánh với các công cụ lập mô hình dữ liệu.

Sẽ rất tuyệt nếu họ ném một ngoại lệ mô tả hơn, và có thể họ sẽ ở trong một phiên bản tương lai. (Damien/Matt ...?)

1

Tại sao bạn làm UpdateJobMaster trên một phiên bản mới? Nó có nên được InsertOnSubmit?

JobMaster newJobToCreate = new JobMaster(); 
newJobToCreate.JobID = 9999 
newJobToCreate.ProjectID = "New Project"; 
this.InsertOnSubmit(newJobToCreate); 
this.SubmitChanges(); 
+0

Tôi đã thay đổi thành InsertOnSubmit, vẫn gặp lỗi tương tự – ben

4

Bạn có thể tạo một lớp học phần cho DataContext của bạn và sử dụng tạo hoặc những gì đã bạn phương pháp từng phần để thiết lập các bản ghi vào Console.Out bọc trong một DEBUG # nếu .. điều này sẽ giúp bạn để xem truy vấn được thực hiện trong khi gỡ lỗi bất kỳ phiên bản nào của datacontext bạn đang sử dụng.

Tôi đã tìm thấy hữu ích LINQ trong khi gỡ lỗi này ngoại lệ SQL ..

partial void OnCreated() 
{ 
#if DEBUG 
     this.Log = Console.Out; 
#endif 
} 
6

hành động gỡ lỗi đầu tiên của tôi sẽ nhìn vào SQL tạo:

JobMaster newJobToCreate = new JobMaster(); 
newJobToCreate.JobID = 9999 
newJobToCreate.ProjectID = "New Project"; 
this.UpdateJobMaster(newJobToCreate); 
this.Log = Console.Out; // prints the SQL to the debug console 
this.SubmitChanges(); 

Thứ hai sẽ là để nắm bắt các ChangeConflictException và có một cái nhìn tại các chi tiết của thất bại.

catch (ChangeConflictException e) 
    { 
    Console.WriteLine("Optimistic concurrency error."); 
    Console.WriteLine(e.Message); 
    Console.ReadLine(); 
    foreach (ObjectChangeConflict occ in db.ChangeConflicts) 
    { 
     MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType()); 
     Customer entityInConflict = (Customer)occ.Object; 
     Console.WriteLine("Table name: {0}", metatable.TableName); 
     Console.Write("Customer ID: "); 
     Console.WriteLine(entityInConflict.CustomerID); 
     foreach (MemberChangeConflict mcc in occ.MemberConflicts) 
     { 
     object currVal = mcc.CurrentValue; 
     object origVal = mcc.OriginalValue; 
     object databaseVal = mcc.DatabaseValue; 
     MemberInfo mi = mcc.Member; 
     Console.WriteLine("Member: {0}", mi.Name); 
     Console.WriteLine("current value: {0}", currVal); 
     Console.WriteLine("original value: {0}", origVal); 
     Console.WriteLine("database value: {0}", databaseVal); 
     } 
    } 
    } 
+0

Ứng dụng của tôi không bao giờ thực sự tạo ra SQL và nó không tạo ra bất kỳ ChangeConflictExceptions nào, nó đang ném bom trước bước này. – ben

+3

Đẹp nhất. Đối với những kẻ sử dụng ASP.Net, chỉ cần thay thế Console. thông qua Gỡ lỗi. để có được kết quả đầu ra trong cửa sổ Output (Đầu ra) – citronas

0

Chúng tôi đã thực sự ngừng sử dụng trình thiết kế LINQ to SQL cho các dự án lớn của chúng tôi và vấn đề này là một trong những lý do chính. Chúng tôi cũng thay đổi rất nhiều giá trị mặc định cho tên, loại dữ liệu và mối quan hệ và mỗi lần trong khi nhà thiết kế sẽ mất những thay đổi đó.Tôi chưa bao giờ tìm được lý do chính xác và tôi không thể tái tạo nó một cách đáng tin cậy.

Điều đó, cùng với những hạn chế khác khiến chúng tôi bỏ thiết kế và thiết kế các lớp học bằng tay. Sau khi chúng tôi đã quen với các mẫu, nó thực sự dễ dàng hơn so với việc sử dụng các nhà thiết kế.

0

Tôi đã đăng câu hỏi tương tự trước đây hôm nay tại đây: Strange LINQ Exception (Index out of bounds).

Đó là một trường hợp sử dụng khác - nơi lỗi này xảy ra trong một SubmitChanges(), của tôi xảy ra trong một truy vấn đơn giản, nhưng nó cũng là một lỗi ngoài chỉ mục.

niêm yết chéo trong câu hỏi này trong trường hợp sự kết hợp của dữ liệu trong các câu hỏi giúp một câu trả lời Samaritan tốt hoặc :)

0

Kiểm tra xem tất cả các "khóa chính" cột trong dbml của bạn thực sự liên quan đến các phím chính trên các bảng cơ sở dữ liệu. Tôi chỉ có một tình huống mà nhà thiết kế đã quyết định đặt thêm một cột PK trong dbml, có nghĩa là LINQ to SQL không thể tìm thấy cả hai mặt của khóa ngoại khi lưu.

0

Gần đây tôi đã gặp phải cùng một vấn đề: những gì tôi đã làm là

Proce proces = unit.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes 
                     where pt.Name == "Fix-O" 
                     select pt).Single().ProcesTypeId && 
                     u.UnitId == UnitId); 

Thay vì:

Proce proces = context.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes 
                    where pt.Name == "Fix-O" 
                    select pt).Single().ProcesTypeId && 
                    u.UnitId == UnitId); 

đâu bối cảnh rõ ràng là đối tượng DataContext và "đơn vị" một thể hiện của đối tượng Unit, một Lớp dữ liệu từ tệp dbml.

Tiếp theo, tôi đã sử dụng đối tượng "bắt đầu" để đặt thuộc tính trong một thể hiện của đối tượng Lớp dữ liệu khác. Có lẽ động cơ LINQ không thể kiểm tra xem thuộc tính mà tôi đã thiết lập từ đối tượng "proce", được cho phép trong lệnh INSERT sẽ được tạo bởi LINQ để thêm đối tượng Lớp dữ liệu khác vào cơ sở dữ liệu.

30

Tôi luôn thấy hữu ích khi biết chính xác những thay đổi nào đang được gửi đến DataContext trong phương thức SubmitChanges().

Tôi sử dụng phương thức DataContext.GetChangeSet(), nó trả về một đối tượng ChangeSet đối tượng chứa 3 đối tượng chỉ đọc của IList đã được thêm, sửa đổi hoặc xóa.

Bạn có thể đặt một breakpoint ngay trước khi gọi phương thức SubmitChanges, và thêm một Watch (hoặc Quick Watch) có chứa:

ctx.GetChangeSet(); 

đâu ctx là trường hợp hiện tại của DataContext của bạn, và sau đó bạn sẽ có có thể theo dõi tất cả các thay đổi sẽ có hiệu lực trong cuộc gọi SubmitChanges.

0

Tôi có cùng lỗi không nói.

Tôi có mối quan hệ khóa ngoài với cột của bảng không phải là khóa chính của bảng, mà là một cột duy nhất. Khi tôi thay đổi cột duy nhất thành khóa chính của bảng, sự cố đã biến mất.

Hy vọng điều này sẽ giúp mọi người!

0

văn kinh nghiệm của tôi với ngoại lệ này trong một câu trả lời cho SO # 237415

1

này gần như chắc chắn sẽ không được mọi người nguyên nhân gốc rễ, nhưng tôi gặp phải ngoại lệ chính xác cùng này trong dự án của tôi - và thấy rằng nguyên nhân gốc rễ là rằng một ngoại lệ đã bị ném trong khi xây dựng một lớp thực thể. Kỳ lạ thay, ngoại lệ thực sự là "bị mất" và thay vào đó biểu hiện dưới dạng ngoại lệ ArgumentOutOfRange bắt nguồn từ trình lặp của câu lệnh Linq để truy lục đối tượng/s.

Nếu bạn nhận được lỗi này và bạn đã giới thiệu phương pháp OnCreated hoặc OnLoaded trên POCO của bạn, hãy thử bước qua các phương pháp đó.

2

Đây là những gì tôi đã làm

... 
var builder = new StringBuilder(); 
try 
{ 
    context.Log = new StringWriter(builder); 
    context.MY_TABLE.InsertAllOnSubmit(someData); 
    context.SubmitChanges();     
} 
finally 
{ 
    Log.InfoFormat("Some meaningful message here... ={0}", builder); 
} 
0

tôi đã kết thúc về câu hỏi này khi cố gắng để gỡ lỗi LINQ ChangeConflictException tôi. Cuối cùng, tôi nhận ra vấn đề là tôi đã thêm thuộc tính vào bảng trong tệp DBML theo cách thủ công, nhưng tôi quên đặt thuộc tính như Nullable (phải đúng trong trường hợp của tôi) và Loại dữ liệu máy chủ

Hy vọng điều này sẽ giúp ai đó.