2009-08-21 13 views
6

Tengo 2 preguntas relacionadas de Linq a SQL. Por favor, mira la imagen a continuación para ver cómo se ve mi modelo.Carga ansiosa de Linq a Entidades SQL en una tabla autorreferenciada

Pregunta 1

Estoy tratando de averiguar cómo se carga el campo User.AddedByUser en mi clase User/table ansiosos. Este campo se genera a partir de la relación en el campo User.AddedByUserId. La tabla se refiere a sí misma, y ​​estoy tratando de averiguar cómo obtener Linq en SQL para cargar la propiedad User.AddedByUser con impaciencia, es decir, cada vez que se cargue/recupere cualquier entidad User, también debe obtener el User.AddedByUser y User.ChangedByUser . Sin embargo, entiendo que esto podría convertirse en un problema recurrente ...

Actualización 1.1:

He tratado de utilizar las DataLoadOptions de la siguiente manera:

var options = new DataLoadOptions(); 
options.LoadWith<User>(u => u.ChangedByUser); 
options.LoadWith<User>(u => u.AddedByUser); 

db = new ModelDataContext(connectionString); 
db.LoadOptions = options; 

pero esto no significa trabajo, tengo la siguiente excepción en la Línea 2:

System.InvalidOperationException occurred 
    Message="Cycles not allowed in LoadOptions LoadWith type graph." 
    Source="System.Data.Linq" 
    StackTrace: 
     at System.Data.Linq.DataLoadOptions.ValidateTypeGraphAcyclic() 
     at System.Data.Linq.DataLoadOptions.Preload(MemberInfo association) 
     at System.Data.Linq.DataLoadOptions.LoadWith[T](Expression`1 expression) 
     at i3t.KpCosting.Service.Library.Repositories.UserRepository..ctor(String connectionString) in C:\Development\KP Costing\Trunk\Code\i3t.KpCosting.Service.Library\Repositories\UserRepository.cs:line 15 
    InnerException: 

la excepción es bastante explica por sí mismo - no está permitido el gráfico de objetos ser cíclico Además, suponiendo que la Línea 2 no arrojó una excepción, estoy bastante seguro de que la Línea 3 lo haría, ya que son claves duplicadas.

actualización 1.2:

El siguiente no funciona bien (no se utiliza en conjunción con Actualización 1.1 arriba):

var query = from u in db.Users 
      select new User() 
      { 
       Id = u.Id, 
       // other fields removed for brevityy 
       AddedByUser = u.AddedByUser, 
       ChangedByUser = u.ChangedByUser, 

      }; 
return query.ToList(); 

Se lanza la siguiente, excepción explica por sí mismo:

System.NotSupportedException occurred 
Message="Explicit construction of entity type 'i3t.KpCosting.Shared.Model.User' in query is not allowed." 

ahora estoy realmente en una pérdida sobre cómo resolver esto. ¡Por favor ayuda!

Pregunta 2

En cada mesa en mi base de datos, y por lo tanto LINQ to modelo de SQL, tengo dos campos, Entity.ChangedByUser (vinculado a Entity.ChangedByUserId clave/relación extranjera) y Entity.AddedByUser (Relacionada con Entity.AddedByUserId clave externa/relación)

¿Cómo obtengo Linq a SQL para que cargue estos campos por e-mail? ¿Debo hacer un simple join en mis consultas ?, ¿o hay alguna otra manera?

Linq to SQL eager loading on self referencing table http://img245.imageshack.us/img245/5631/linqtosql.jpg

Respuesta

3

Tal vez podría tratar de dar un paso atrás y ver lo que quiere hacer con la relación? Supongo que desea mostrar esta información al usuario, p. "modificado por Iain Galloway hace 8 horas".

¿Algo así como el siguiente trabajo? : -

var users = from u in db.Users 
      select new 
      { 
       /* other stuff... */ 
       AddedTimestamp = u.AddedTimestamp, 
       AddedDescription = u.AddedByUser.FullName, 
       ChangedTimestamp = u.ChangedTimestamp, 
       ChangedDescription = u.ChangedByUser.FullName 
      }; 

He usado un tipo anónimo allí para (imo) claridad. Puede agregar esas propiedades a su Tipo de usuario si lo prefiere.

En cuanto a su segunda pregunta, su LoadWith normal (x => x.AddedByUser) etc. debería funcionar bien, aunque tiendo a preferir almacenar la cadena de descripción directamente en la base de datos, tiene una compensación entre su descripción que se actualiza cuando ChangedByUser.FullName cambia y tiene que hacer algo complicado y posiblemente contrario a la intuición si el ChangedByUser se elimina (por ejemplo, ON DELETE CASCADE, o tratar con un ChangedByUser nulo en su código).

+0

Sí, sí quiero mostrar esa información en mi GUI. Esperaba resolver este problema sin el uso de tipos anónimos. Pero supongo que ES una forma de resolver el problema. ¿Mi problema está relacionado con la incapacidad de Linq para SQL para hacer frente a muchas o muchas relaciones? –

+0

Na, podría agregar los campos User.AddedDescription y User.ChangedDescription a la clase User y luego no tendría que usar un tipo anon. No tiene nada que ver con la relación many-many (cada relación en su ejemplo es 1: 1). Si estaba escribiendo su SQL directamente, no le gustaría obtener todas las propiedades de AddedByUser (incluyendo su AddedByUser y así sucesivamente hasta el infinito). Probablemente solo tomarías su nombre y/o los detalles que necesites para tu vista. Imo es un problema general de O/RM. Creo que tendrías el mismo problema con L2E o Hibernate. –

0

No estoy seguro de que hay una solución a este problema con LINQ to SQL. Si está utilizando Sql Server 2005, puede definir un procedimiento almacenado (recursivo) que utilice expresiones de tabla comunes para obtener el resultado que desee y luego ejecutarlo usando DataContext.ExecuteQuery.

4

Any type of cycles just aren't allowed. Dado que LoadWith<T> o AssociateWith<T> se aplican a todos los tipos del contexto, no existe una forma interna de evitar un bucle infinito. Más exactamente, simplemente se confunde sobre cómo crear el SQL, ya que SQL Server no tiene CONNECT BY y CTEs son realmente más allá de lo que Linq puede generar automáticamente con el marco provisto.

La mejor opción disponible para usted es hacer manualmente la unión de 1 nivel hasta la tabla de usuario para que ambos niños y un tipo anónimo los devuelvan. Lo siento, no es una solución limpia/fácil, pero en realidad es todo lo que está disponible hasta ahora con Linq.

Cuestiones relacionadas