Мне очень трудно отлаживать LINQ to SQL и отправлять изменения.
Я использовал http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx, который отлично подходит для отладки простых запросов.
Я работаю в классе DataContext для своего проекта со следующим фрагментом из моего приложения:
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.SubmitChanges();
Я поймаю несколько очень странных исключений, когда запущу this.SubmitChanges;
Index was outside the bounds of the array.
Трассировка стека идет туда, куда я не могу войти:
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
У кого-нибудь есть какие-нибудь инструменты или методы, которые они используют? Я упустил что-то простое?
РЕДАКТИРОВАТЬ: Я настроил отладку .net, используя предложение Slace, однако код .net 3.5 еще не доступен: http://referencesource.microsoft.com/netframework.aspx
РЕДАКТИРОВАТЬ2: Я перешел на InsertOnSubmit в соответствии с предложением sirrocco, но по-прежнему получаю ту же ошибку.
РЕДАКТИРОВАТЬ3: Я реализовал предложения Сэма, пытаясь зарегистрировать сгенерированный SQL и перехватить ChangeExceptoinException. Эти предложения больше не проливают света, мне никогда не удается сгенерировать SQL, когда возникает мое исключение.
РЕДАКТИРОВАТЬ4: Я нашел ответ, который работает для меня ниже. Это всего лишь теория, но она устранила мою текущую проблему.





Простое решение может заключаться в том, чтобы запустить трассировку вашей базы данных и проверить выполняемые запросы к ней - конечно, с фильтрацией, чтобы отсортировать другие приложения и т. д., Обращающиеся к базе данных.
Это, конечно, помогает только тогда, когда вы преодолеете исключения ...
Грм.
Принимая WAG (Wild Ass Guess), мне кажется, что LINQ - SQL пытается найти объект с несуществующим идентификатором, каким-то образом на основе создания класса JobMaster. Существуют ли внешние ключи, связанные с этой таблицей, так что LINQ to SQL будет пытаться получить экземпляр класса, который может не существовать? Кажется, вы устанавливаете ProjectID нового объекта в строку - действительно ли у вас есть идентификатор, который является строкой? Если вы пытаетесь установить его для нового проекта, вам необходимо создать новый проект и получить его идентификатор.
Наконец, что делает UpdateJobMaster? Может ли он делать что-то такое, что применимо выше?
VS 2008 имеет возможность отладки через платформу .NET (http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx)
Это, вероятно, ваш лучший выбор, вы можете видеть, что происходит, и какие все свойства находятся в точный момент времени.
На сегодняшний день linksource.microsoft.com/netframework.aspx исходный код для .net 3.5 еще не доступен.
Ошибка, о которой вы говорите выше, обычно вызвана ассоциации, указывающие в неправильном направлении. Это происходит очень легко при добавлении ассоциаций в конструктор вручную, поскольку стрелки ассоциаций в конструкторе L2S указывают назад по сравнению с инструментами моделирования данных.
Было бы неплохо, если бы они выделили более описательное исключение, и, возможно, они это сделают в будущей версии. (Дэмиен / Мэтт ...?)
Почему вы делаете UpdateJobMaster на новом экземпляре? Разве это не должно быть InsertOnSubmit?
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.InsertOnSubmit(newJobToCreate);
this.SubmitChanges();
Вы можете создать частичный класс для своего DataContext и использовать метод Created или какой у вас частичный, чтобы настроить журнал на console.out, завернутый в #if DEBUG .. это поможет вам увидеть выполняемые запросы при отладке любого экземпляра используемый вами текст данных.
Я нашел это полезным при отладке исключений LINQ to SQL.
partial void OnCreated()
{
#if DEBUG
this.Log = Console.Out;
#endif
}
Моим первым действием отладки было бы посмотреть на сгенерированный SQL:
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();
Второй - перехватить ChangeConflictException и изучить подробности сбоя.
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);
}
}
}
Мое приложение на самом деле никогда не генерирует SQL и не генерирует никаких исключений ChangeConflictExceptions, оно взрывается перед этим шагом.
Хороший. Для парней, использующих ASP.Net, просто замените Console. через Debug. чтобы получить результат в окне вывода
Во-первых, спасибо всем за помощь, наконец-то нашел.
Решение заключалось в том, чтобы удалить файл .dbml из проекта, добавить пустой файл .dbml и заново заполнить его таблицами, необходимыми для моего проекта, из «Server Explorer».
Я заметил несколько вещей, пока делал это:
Это всего лишь теория. Если кто-то может лучше объяснить это, я хотел бы получить здесь конкретный ответ.
Кто-то создал связь от одного объекта к другому, где внешний конец не был первичным ключом. Это ошибка в 3.5 SP1.
Мы фактически перестали использовать конструктор Linq to SQL для наших крупных проектов, и эта проблема является одной из основных причин. Мы также меняем множество значений по умолчанию для имен, типов данных и отношений, и время от времени дизайнер теряет эти изменения. Я так и не нашел точной причины и не могу достоверно воспроизвести ее.
Это, наряду с другими ограничениями, заставило нас отказаться от дизайнера и разрабатывать классы вручную. После того, как мы привыкли к выкройкам, это на самом деле проще, чем пользоваться конструктором.
Сегодня я уже задавал похожий вопрос здесь: Странное исключение LINQ (индекс выходит за границы).
Это другой вариант использования - когда эта ошибка возникает во время SubmitChanges (), моя возникает во время простого запроса, но это также ошибка индекса вне допустимого диапазона.
Перекрестная публикация в этом вопросе в случае, если комбинация данных в вопросах также помогает дать хороший самаритянин ответ :)
Убедитесь, что все столбцы «первичного ключа» в вашем dbml действительно относятся к первичным ключам в таблицах базы данных. У меня была ситуация, когда дизайнер решил добавить дополнительный столбец PK в dbml, что означало, что LINQ to SQL не мог найти обе стороны внешнего ключа при сохранении.
Недавно я столкнулся с той же проблемой: то, что я сделал, было
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);
Вместо:
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);
Где контекст, очевидно, был объектом DataContext, а «unit» - экземпляром объекта Unit, классом данных из файла dbml.
Затем я использовал объект "proc", чтобы установить свойство в экземпляре другого объекта класса данных. Вероятно, механизм LINQ не смог проверить, разрешено ли свойство, которое я устанавливал из объекта "process", в команде INSERT, которая должна была быть создана LINQ для добавления другого объекта класса данных в базу данных.
Мне всегда было полезно знать, какие именно изменения отправляются в DataContext в методе SubmitChanges ().
Я использую метод DataContext.GetChangeSet (), он возвращает экземпляр объекта ChangeSet, который содержит 3 доступных только для чтения IList объектов, которые были добавлены, изменены или удалены.
Вы можете разместить точку останова непосредственно перед вызовом метода SubmitChanges и добавить Watch (или Quick Watch), содержащий:
ctx.GetChangeSet();
Где ctx - это текущий экземпляр вашего DataContext, и тогда вы сможете отслеживать все изменения, которые будут действовать при вызове SubmitChanges.
У меня была такая же ошибка без слов.
У меня было отношение внешнего ключа к столбцу таблицы, который был не первичным ключом таблицы, а уникальным столбцом. Когда я изменил уникальный столбец на первичный ключ таблицы, проблема исчезла.
Надеюсь, это кому-нибудь поможет!
Опубликовал мой опыт с этим исключением в ответе на SO # 237415
Это почти наверняка не будет основной причиной для всех, но я столкнулся с тем же самым исключением в своем проекте - и обнаружил, что основная причина заключалась в том, что исключение было выброшено во время создания класса сущности. Как ни странно, истинное исключение «потеряно» и вместо этого проявляется как исключение ArgumentOutOfRange, возникающее в итераторе оператора Linq, который извлекает объект / объекты.
Если вы получаете эту ошибку и ввели методы OnCreated или OnLoaded в свои объекты POCO, попробуйте выполнить эти методы.
Это то, что я сделал
...
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);
}
Я столкнулся с этим вопросом, пытаясь отладить свое исключение LINQ ChangeConflictException. В конце концов я понял, что проблема в том, что я вручную добавил свойство в таблицу в моем файле DBML, но я забыл установить такие свойства, как Обнуляемый (в моем случае это должно было быть правдой) и Тип данных сервера
Надеюсь, это кому-то поможет.
Это было давно, но у меня была такая же проблема, и ошибка возникла из-за триггера с оператором select. Что-то вроде
CREATE TRIGGER NAME ON TABLE1 AFTER UPDATE AS SELECT table1.key from table1
inner join inserted on table1.key = inserted.key
Когда linq-to-sql запускает команду обновления, он также запускает оператор select для получения автоматически сгенерированных значений в том же запросе и ожидает, что первый набор записей будет содержать столбцы, «запрошенные», но в этом случае первая строка была столбцы из оператора выбора в триггере. Итак, linq-to-sql ожидал два автоматически сгенерированных столбца, но получил только один столбец (с неправильными данными), и это вызвало это исключение.
Эта ошибка возникала у многих клиентов, только на машинах с Windows XP я нашел это оперативное исправление, которое решило проблему. i386 и x64