Отладка LINQ to SQL SubmitChanges ()

Мне очень трудно отлаживать 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: Я нашел ответ, который работает для меня ниже. Это всего лишь теория, но она устранила мою текущую проблему.

Эта ошибка возникала у многих клиентов, только на машинах с Windows XP я нашел это оперативное исправление, которое решило проблему. i386 и x64

gpiccin 26.05.2013 01:12
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
21
1
28 137
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

Простое решение может заключаться в том, чтобы запустить трассировку вашей базы данных и проверить выполняемые запросы к ней - конечно, с фильтрацией, чтобы отсортировать другие приложения и т. д., Обращающиеся к базе данных.

Это, конечно, помогает только тогда, когда вы преодолеете исключения ...

Грм.

Принимая 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 еще не доступен.

ben 18.09.2008 18:28

Ошибка, о которой вы говорите выше, обычно вызвана ассоциации, указывающие в неправильном направлении. Это происходит очень легко при добавлении ассоциаций в конструктор вручную, поскольку стрелки ассоциаций в конструкторе 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, оно взрывается перед этим шагом.

ben 19.09.2008 18:10

Хороший. Для парней, использующих ASP.Net, просто замените Console. через Debug. чтобы получить результат в окне вывода

citronas 05.01.2012 18:16
Ответ принят как подходящий

Во-первых, спасибо всем за помощь, наконец-то нашел.

Решение заключалось в том, чтобы удалить файл .dbml из проекта, добавить пустой файл .dbml и заново заполнить его таблицами, необходимыми для моего проекта, из «Server Explorer».

Я заметил несколько вещей, пока делал это:

  • В системе есть несколько таблиц, имена которых состоят из двух слов и пробела между ними, например, «Мастер вакансий». Когда я перетаскивал эту таблицу обратно в файл .dbml, она создавала таблицу с именем «Job_Master», она заменяла пробел символом подчеркивания.
  • В исходном файле .dbml один из моих разработчиков просмотрел файл .dbml и удалил все символы подчеркивания, поэтому «Job_Master» превратился бы в «JobMaster» в файле .dbml. Затем в коде мы могли бы ссылаться на таблицу в более стандартном для нас соглашении об именах.
  • Моя теория заключается в том, что где-то перевод с «JobMaster» на «Job Master» был утерян при выполнении проекции, и я продолжал придумывать ошибку массива вне пределов.

Это всего лишь теория. Если кто-то может лучше объяснить это, я хотел бы получить здесь конкретный ответ.

Кто-то создал связь от одного объекта к другому, где внешний конец не был первичным ключом. Это ошибка в 3.5 SP1.

DamienG 18.07.2009 02:12

Мы фактически перестали использовать конструктор 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 ожидал два автоматически сгенерированных столбца, но получил только один столбец (с неправильными данными), и это вызвало это исключение.

Другие вопросы по теме