Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LinqToSql and abstract base classes

Tags:

c#

linq-to-sql

I have some linq entities that inherit something like this:

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
{
}

In a generic method I am querying DeviceEnityBase derived entities with:

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

where TEntity has a contraint that is it a DeviceEntityBase. This query is always failing with an InvalidOperationException with the message "Class member DeviceEntityBase.DeviceId is unmapped". Even if I add some mapping info in the abstract base class with

[Column(Storage = "_DeviceId", DbType = "Int", Name = "DeviceId", IsDbGenerated = false, UpdateCheck = UpdateCheck.Never)]
like image 631
Nic Strong Avatar asked Oct 01 '08 03:10

Nic Strong


People also ask

What is base class and abstract class?

Abstract classes are classes which cannot be instantiated. They exist to provide common functionality and interface specifications to several concrete classes................. In Object Oriented Programming, a base class is one from which other classes inherit.

What are abstract and virtual base classes describe?

3.3. 1 Abstract Base Classes. An ABC is a class that contains one or more pure virtual member functions. Such a class is not concrete and cannot be instantiated using the new operator. Instead, it is used as a base class where derived classes provide the implementations of the pure virtual methods.

What is abstract base class in OOP?

An abstract class is a class that is designed to be specifically used as a base class. An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier ( = 0 ) in the declaration of a virtual member function in the class declaration.

What is special about abstract base classes?

Abstract base classes cannot be instantiated. Instead, they are inherited and extended by the concrete subclasses. Subclasses derived from a specific abstract base class must implement the methods and properties provided in that abstract base class. Otherwise, an error is raised during the object instantiation.


3 Answers

Wow, looks like for once I may be able to one-up @MarcGravell!

I had the same problem, then I discovered this answer, which solved the problem for me!

In your case, you would say:

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

and Bob's your uncle!

like image 176
Shaul Behr Avatar answered Sep 26 '22 16:09

Shaul Behr


LINQ-to-SQL has some support for inheritance via a discriminator (here, here), but you can only query on classes that are defined in the LINQ model - i.e. data classes themselves, and (more perhaps importantly for this example) the query itself must be phrased in terms of data classes: although TEntity is a data class, it knows that the property here is declared on the entity base.

One option might be dynamic expressions; it the classes themselves declared the property (i.e. lose the base class, but keep the interface) - but this isn't trivial.

The Expression work would be something like below, noting that you might want to either pass in the string as an argument, or obtain the primary key via reflection (if it is attributed):

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);
}
like image 43
Marc Gravell Avatar answered Sep 24 '22 16:09

Marc Gravell


This kind of heirarchial mapping isnot possible with LinqToSql. The the mapping is setup it cannot map to properties in base classes. I went around on this for a couple of months when it first came out. The best solution is to use the entity framework. It gives you much more flexibility with creating your object model. It will allow you to do exactly what your trying to do here.

Here is some information on the entity framework: MSDN Article

like image 20
Micah Avatar answered Sep 26 '22 16:09

Micah