2008-10-01 13 views
6

tengo algunas entidades LINQ que heredan algo como esto:LinqToSql y base abstracta clases

public abstract class EntityBase { public int Identifier { get; } } 

public interface IDeviceEntity { int DeviceId { get; set; } } 

public abstract class DeviceEntityBase : EntityBase, IDeviceEntity 
{ 
    public abstract int DeviceId { get; set; } 
} 

public partial class ActualLinqGeneratedEntity : DeviceEntityBase 
{ 
} 

En un método genérico que estoy consultando entidades DeviceEnityBase derivados con:

return unitOfWork.GetRepository<TEntity>().FindOne(x => x.DeviceId == evt.DeviceId); 

donde TEntity tiene una contraint eso es un DeviceEntityBase. Esta consulta siempre está fallando con InvalidOperationException con el mensaje "El miembro de la clase DeviceEntityBase.DeviceId no está mapeado". Incluso si añado algo de información de asignación en la clase base abstracta con

[Column(Storage = "_DeviceId", DbType = "Int", Name = "DeviceId", IsDbGenerated = false, UpdateCheck = UpdateCheck.Never)] 

Respuesta

4

LINQ a SQL tiene algunos apoyo a la herencia a través de un discriminador (here, here), pero sólo se puede consultar en las clases que se definen en el modelo LINQ - es decir, las clases de datos y (más importante aún para este ejemplo) la consulta en sí misma debe redactarse en términos de clases de datos: aunque TEntity es una clase de datos, sabe que la propiedad aquí se declara en la base de la entidad.

Una opción podría ser expresiones dinámicas; las propias clases declararon la propiedad (es decir, pierden la clase base, pero conservan la interfaz), pero esto no es trivial.

El trabajo Expresión sería algo así como más adelante, observando que es posible que desee o bien pasar en la cadena como un argumento, u obtener la clave principal a través de la reflexión (si se le atribuye):

static Expression<Func<T, bool>> BuildWhere<T>(int deviceId) { 
    var id = Expression.Constant(deviceId, typeof(int)); 
    var arg = Expression.Parameter(typeof(T), "x"); 
    var prop = Expression.Property(arg, "DeviceId"); 
    return Expression.Lambda<Func<T, bool>>(
     Expression.Equal(prop, id), arg); 
} 
1

Este tipo de mapeo heirarchial isnot posible con LinqToSql. El mapeo está configurado, no puede mapear a las propiedades en las clases base. Estuve hablando de esto por un par de meses cuando salió por primera vez. La mejor solución es usar el marco de entidad. Le da mucha más flexibilidad al crear su modelo de objetos. Te permitirá hacer exactamente lo que tratas de hacer aquí.

Aquí hay alguna información en el marco de la entidad: MSDN Article

5

Wow , parece que por una vez puedo ser capaz de one-up @MarcGravell!

Tuve el mismo problema, entonces descubrí this answer, lo que me solucionó el problema.

En su caso, usted podría decir:

return unitOfWork.GetRepository<TEntity>().Select(x => x).FindOne(x => x.DeviceId == evt.DeviceId); 

y Bob es tu tío!

+1

@Lijo - Creo que la respuesta de Ladislav es buena ... –

+0

Gracias. Pero eso no será "programación a una interfaz", ¿no es así? A continuación se muestra un comentario de Scott en http://weblogs.asp.net/scottgu/archive/2007/06/29/linq-to-sql-part-3-querying-our-database.aspx - "Agregar las interfaces con sus clases de modelo de datos LINQ to SQL. Las clases LINQ to SQL son parciales, lo que significa que puede agregar la interfaz directamente a ellas. " Esta sugerencia no funciona en nuestro escenario. ¿Hay alguna manera de hacerlo funcionar? – Lijo

Cuestiones relacionadas