Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ, entity that implements Interface and exception in mapping

I'm using repository pattern with LINQ, have IRepository.DeleteOnSubmit(T Entity). It works fine, but when my entity class has interface, like this:

public interface IEntity { int ID {get;set;} }

public partial class MyEntity: IEntity {

    public int ID { 
        get { return this.IDfield; }
        set { this.IDfield=value;  }
    }
}

and then trying to delete some entity like this:

IEntity ie=repository.GetByID(1);
repoitory.DeleteOnSubmit(ie);

throws
The member 'IEntity.ID' has no supported translation to SQL.

fetching data from DB works, but delete and insert doesn't. How to use interface against DataContext?


Here it is:
Exception message: The member 'MMRI.DAL.ITag.idContent' has no supported translation to SQL.

Code:

var d = repContent.GetAll().Where(x => x.idContent.Equals(idContent));
foreach (var tagConnect in d)    <- error line
{
    repContet.DeleteOnSubmit(tagConnect);

(it gets all tags from DB, and deletes them)

And stack trace:

[NotSupportedException: The member 'MMRI.DAL.ITag.idContent' has no supported translation to SQL.]
   System.Data.Linq.SqlClient.Visitor.VisitMember(SqlMember m) +621763
   System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node) +541
   System.Data.Linq.SqlClient.SqlVisitor.VisitExpression(SqlExpression exp) +8
   System.Data.Linq.SqlClient.SqlVisitor.VisitBinaryOperator(SqlBinary bo) +18
   System.Data.Linq.SqlClient.Visitor.VisitBinaryOperator(SqlBinary bo) +18
   System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node) +196
   System.Data.Linq.SqlClient.SqlVisitor.VisitExpression(SqlExpression exp) +8
   System.Data.Linq.SqlClient.SqlVisitor.VisitSelectCore(SqlSelect select) +46
   System.Data.Linq.SqlClient.Visitor.VisitSelect(SqlSelect select) +20
   System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node) +1024
   System.Data.Linq.SqlClient.SqlProvider.BuildQuery( ...

When I try do decorate partial class:

[Column(Storage = "_idEvent", DbType = "Int NOT NULL", IsPrimaryKey = true)]
public int idContent
{ get { return this.idEvent; } set { this.idEvent=value; } }

it throws error "Invalid column name 'idContent'."

like image 905
Hrvoje Hudo Avatar asked Aug 18 '08 09:08

Hrvoje Hudo


2 Answers

It appears Microsoft dropped support for == operator in interfaces when using linq-to-sql in MVC4 (or maybe it was never supported). You can however use i.ID.Equals(someId) in place of the == operator.

Casting IQueryable to IEnumerable works but should not be used! The reason is: IQueryable has funky implementation of IEnumerable. Whatever linq method you'll use on a IQueryable through the IEnumerable interface will cause the query to be executed first, have all the results fetched to the memory from the DB and eventually running the method localy on the data (normally those methods would be translated to SQL and executed in the DB). Imagine trying to get a single row from a table containing billion rows, fetching all of them only to pick one (and it gets much worse with careless casting of IQueryable to IEnumerable and lazy loading related data).

Apparently Linq has no problem using == operator with interfaces on local data (so only IQueryable is affected) and also with Entity Frameworks (or so I heard).

like image 119
jahu Avatar answered Nov 10 '22 11:11

jahu


This works for me -

public partial class MyEntity: IEntity 
 {    [Column(Name = "IDfield", Storage = "_IDfield", IsDbGenerated = true)]
      public int ID 
       {         
          get { return this.IDfield; }        
          set { this.IDfield=value;  }    
       } 
 }
like image 22
Frank Tzanabetis Avatar answered Nov 10 '22 11:11

Frank Tzanabetis