2008-09-17 14 views
21

Estoy teniendo un momento muy difícil tratar de depuración LINQ a SQL y enviar los cambios.Depuración LINQ a SQL SubmitChanges()

He estado usando http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx, que funciona muy bien para la depuración de consultas simples.

estoy trabajando en la clase DataContext para mi proyecto con el siguiente fragmento de mi aplicación:

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

voy a coger algunas excepciones muy raras cuando corro this.SubmitChanges;

Index was outside the bounds of the array. 

El seguimiento de la pila va lugares en los que no se puede recorrer:

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 

¿Alguien tiene herramientas o técnicas que utilizan? ¿Me estoy perdiendo algo simple?

EDITAR: he configurar .net depuración utilizando la sugerencia de Slace, sin embargo el código .NET 3.5 aún no está disponible: http://referencesource.microsoft.com/netframework.aspx

Edit2: he cambiado a InsertOnSubmit según la Sirrocco sugerencia, sigue recibiendo el mismo error.

Edit3: he implementado sugerencias de Sam intentar registrar el SQL generado y para coger el ChangeExceptoinException. Estas sugerencias no arrojan más luz, nunca voy a generar SQL cuando se lanza mi excepción.

EDIT4: he encontrado una respuesta que me funciona a continuación. Es solo una teoría pero ha solucionado mi problema actual.

+0

Este error ocurrió con muchos clientes, solo en máquinas con Windows XP, encontré este hot-fix que resolvió el problema. [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/free/448814_intl_i386_zip.exe) y [x64] (http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=963657&kbln=en-us) – gpiccin

Respuesta

8

Primero, gracias a todos por la ayuda, finalmente lo encontré.

La solución fue soltar el archivo .dbml del proyecto, agregar un archivo .dbml en blanco y volver a llenarlo con las tablas necesarias para mi proyecto desde 'Server Explorer'.

me di cuenta de un par de cosas mientras yo estaba haciendo esto:

  • Hay algunas mesas en el sistema de nombre con dos palabras y un espacio entre las palabras, es decir, 'Maestro de empleo'. Cuando estaba volviendo a colocar esa tabla en el archivo .dbml crearía una tabla llamada 'Job_Master', que reemplazaría el espacio con un guión bajo.
  • En el archivo .dbml original, uno de mis desarrolladores había revisado el archivo .dbml y eliminado todos los caracteres de subrayado, por lo que 'Job_Master' se convertiría en 'JobMaster' en el archivo .dbml. En el código, podríamos consultar la tabla en una convención de nomenclatura más, para nosotros.
  • Mi teoría es que en algún lugar, la traducción de 'JobMaster' a 'Job Master' mientras se perdía mientras hacía la proyección, y seguí llegando con el error de matriz fuera de límites.

Es solo una teoría. Si alguien puede explicarlo mejor, me encantaría tener una respuesta concreta aquí.

+2

Alguien había creado una asociación de una entidad a otra donde el extremo externo no era la clave principal. Este es un error en 3.5 SP1. – DamienG

1

Una solución sencilla podría ser la de ejecutar un rastro en su base de datos e inspeccionar las consultas ejecutadas en contra de ella - filtrada por supuesto que resolver otras aplicaciones, etc. acceder a la base de datos.

Eso por supuesto sólo ayuda una vez que pasas las excepciones ...

0

Hrm.

Tomar una WAG (Wild Culo Guess), se ve a mí como LINQ - SQL está tratando de encontrar un objeto con un identificador que no existe, en función de alguna manera en la creación de la clase JobMaster. ¿Hay claves externas relacionadas con esa mesa de tal manera que LINQ a SQL sería tratará de coger una instancia de una clase, que no puede existir? Parece que está estableciendo el ProjectID del nuevo objeto en una cadena: ¿realmente tiene una identificación que es una cadena? Si intenta establecerlo en un nuevo proyecto, deberá crear un nuevo proyecto y obtener su identificación.

Por último, ¿qué hace UpdateJobMaster? ¿Podría estar haciendo algo tal que se aplicaría lo anterior?

2

El error se está refiriendo a la anterior es generalmente causada por asociaciones que apuntan en la dirección incorrecta. Esto ocurre muy fácilmente cuando se agregan asociaciones de forma manual al diseñador, ya que las flechas de asociación en el diseñador de L2S apuntan hacia atrás en comparación con las herramientas de modelado de datos.

Sería bueno si arrojasen una excepción más descriptiva, y tal vez lo harán en una versión futura. (Damien/Matt ...?)

1

¿Por qué haces UpdateJobMaster en una nueva instancia? ¿No debería ser InsertOnSubmit?

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

He cambiado a InsertOnSubmit, sigue recibiendo el mismo error – ben

4

Puede crear una clase parcial para su DataContext y utilizar lo creado o lo que sea el método parcial de configurar el registro a la Console.Out envuelto en una DEBUG #if .. esto le ayudará a ver el consultas ejecutadas al depurar cualquier instancia del contexto de datos que está utilizando.

he encontrado esto útil durante la depuración LINQ a SQL excepciones ..

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

Mi primera acción de depuración sería buscar en el SQL generado:

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(); 

La segunda sería la de capturar la ChangeConflictException y eche un vistazo a los detalles de la falla.

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

Mi aplicación nunca está generando SQL y no está generando ninguna ChangeConflictExceptions, está bombardeando antes de este paso. – ben

+3

Bueno. Para los chicos que usan ASP.Net, simplemente reemplacen la consola. a través de Debug. para obtener el resultado en la ventana Salida – citronas

0

De hecho, hemos dejado de utilizar el diseñador Linq to SQL para nuestros proyectos grandes y este problema es uno de los principales. También cambiamos muchos de los valores predeterminados para nombres, tipos de datos y relaciones y de vez en cuando el diseñador perdería esos cambios.Nunca encontré una razón exacta, y no puedo reproducirla de manera confiable.

Eso, junto con las otras limitaciones, nos hizo abandonar el diseñador y diseñar las clases a mano. Después de que nos acostumbramos a los patrones, en realidad es más fácil que usar el diseñador.

0

He publicado una pregunta similar hoy aquí: Strange LINQ Exception (Index out of bounds).

Es un caso de uso diferente, donde ocurre este error durante un SubmitChanges(), el mío ocurre durante una consulta simple, pero también es un error de índice fuera de rango.

envío cruzado en esta pregunta en el caso de la combinación de los datos de las preguntas ayuda a una buena respuesta ya sea Samaritano :)

0

Comprobar que todas las columnas "clave primaria" en su dbml en realidad se refieren a las claves principales en el tablas de base de datos Acabo de tener una situación en la que el diseñador decidió poner una columna PK adicional en el archivo dbml, lo que significaba que LINQ to SQL no podía encontrar las dos caras de una clave externa al guardar.

0

me encontré recientemente el mismo problema: lo que hice fue

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); 

En lugar de:

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); 

Siendo contexto era, obviamente, el objeto DataContext y "unidad" una instancia de objeto de unidad, una Clase de datos de un archivo dbml.

A continuación, utilicé el objeto "proce" para establecer una propiedad en una instancia de otro objeto de clase de datos. Probablemente, el motor LINQ no pudo verificar si la propiedad que estaba configurando desde el objeto "proce" estaba permitida en el comando INSERT que iba a tener que ser creado por LINQ para agregar el otro objeto Data Class a la base de datos.

30

Siempre me ha parecido útil saber exactamente qué cambios se están enviando a DataContext en el método SubmitChanges().

Utilizo el método DataContext.GetChangeSet(), devuelve una instancia de objeto ChangeSet que contiene 3 ILIST de solo lectura de objetos que se han agregado, modificado o eliminado.

Se puede colocar un punto de interrupción justo antes de la llamada al método SubmitChanges, y añadir un reloj (o Inspección rápida) que contiene:

ctx.GetChangeSet(); 

que CTX es la instancia actual de su DataContext, y entonces usted estará capaz de rastrear todos los cambios que serán efectivos en la llamada SubmitChanges.

0

Tuve el mismo error de no hablar.

Tenía una relación de clave externa a una columna de una tabla que no era la clave principal de la tabla, sino una columna única. Cuando cambié la columna única para que fuera la clave principal de la tabla, el problema desapareció.

Espero que esto ayude a cualquiera!

0

Publicado mis experiencias con esta excepción en una respuesta a lo que # 237415

1

Esto es casi seguro que no será de todos raíz del problema, pero me encontré con esta misma excepción exacta en mi proyecto - y encontró que la causa era que se estaba lanzando una excepción durante la construcción de una clase de entidad. Curiosamente, la verdadera excepción es "perdida" y en su lugar se manifiesta como una excepción ArgumentOutOfRange que se origina en el iterador de la instrucción Linq que recupera el/los objeto/s.

Si recibe este error y ha introducido métodos OnCreated o OnLoaded en sus POCO, intente recorrer esos métodos.

2

Esto es lo que hice

... 
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

terminé sobre esta cuestión cuando se trata de depurar mi LINQ ChangeConflictException. Al final me di cuenta de que el problema era que he añadido manualmente una propiedad a una tabla en mi archivo DBML, pero se me olvidó para establecer las propiedades como anulable (debería haber sido cierto en mi caso) y de datos del servidor Tipo

Espero que esto ayude a alguien.

Cuestiones relacionadas