LINQ,在映射中实现接口和异常的实体

时间:2008-08-18 09:28:23

标签: c# linq repository

我正在使用LINQ的存储库模式,有IRepository.DeleteOnSubmit(T Entity)。它工作正常,但当我的实体类有接口时,如下所示:

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

public partial class MyEntity: IEntity {

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

然后尝试删除这样的实体:

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

抛出
成员'IEntity.ID'没有支持的SQL转换。

从数据库中获取数据,但删除和插入不起作用。如何使用DataContext接口?


这是:
异常消息: 成员'MMRI.DAL.ITag.idContent'没有支持的SQL转换。

代码:

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

(它从DB获取所有标签,并删除它们)

堆栈跟踪:

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

当我尝试装饰部分类时:

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

它抛出错误“无效的列名'idContent'。”

4 个答案:

答案 0 :(得分:7)

在MVC4中使用linq-to-sql时,似乎Microsoft在接口中放弃了对==运算符的支持(或者从未支持过)。但是,您可以使用i.ID.Equals(someId)代替==运算符。

IQueryable投射到IEnumerable不应该使用!原因是:IQueryable具有IEnumerable的时髦实现。无论您通过IQueryable接口在IEnumerable上使用哪种linq方法,都会导致首先执行查询,将所有结果从数据库中提取到内存中并最终运行方法localy在数据上(通常这些方法将被转换为SQL并在DB中执行)。想象一下,试图从一个包含十亿行的表中获取一行,只获取所有这些行以选择一行(并且通过不小心将IQueryable转换为IEnumerable和延迟加载相关数据会变得更糟。

显然Linq使用==运算符和本地数据接口(因此只有IQueryable受影响)以及实体框架(或者我听说过)都没有问题。

答案 1 :(得分:3)

这对我有用 -

public partial class MyEntity: IEntity 
 {    [Column(Name = "IDfield", Storage = "_IDfield", IsDbGenerated = true)]
      public int ID 
       {         
          get { return this.IDfield; }        
          set { this.IDfield=value;  }    
       } 
 }

答案 2 :(得分:0)

试试这个:

using System.Data.Linq.Mapping;

public partial class MyEntity: IEntity 
 {    [Column(Storage="IDfield", DbType="int not null", IsPrimaryKey=true)]
      public int ID 
       {         
          get { return this.IDfield; }        
          set { this.IDfield=value;  }    
       } 
 }

答案 3 :(得分:0)

为了将LINQ查询转换为实际的SQL,Linq2SQL会检查您提供的表达式。问题是您没有为L2S提供足够的信息以便能够将“ID”属性转换为实际的DB列名称。您可以通过确保L2S可以将“ID”映射到“IDField”来实现您的目标。

这应该可以使用答案中提供的方法。

如果您使用设计器,您还可以简单地将类属性“IDField”重命名为“ID”,并且还有一个额外的好处,即您不必再在部分类中显式实现“ID”属性,即MyEntity的部分类定义变为:

public partial class MyEntity: IEntity 
{    
}