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

Posted

技术标签:

【中文标题】LINQ,在映射中实现接口和异常的实体【英文标题】:LINQ, entity that implements Interface and exception in mapping 【发布时间】:2010-09-06 01:48:40 【问题描述】:

我在 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);

(它从数据库中获取所有标签,并删除它们)

还有堆栈跟踪:

[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'。”

【问题讨论】:

堆栈溢出不是论坛。您(和其他人)发布为问题的“答案”的一些内容实际上应该是“cmets”。您还可以编辑原始问题和任何答案。 【参考方案1】:

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

IQueryable 转换为IEnumerable 有效,但不应使用!原因是:IQueryable 具有IEnumerable 的时髦实现。无论您将通过IQueryable 接口在IQueryable 上使用什么linq 方法,都会首先执行查询,将所有结果从数据库中提取到内存中,并最终在数据上本地运行该方法(通常是那些方法将被转换为 SQL 并在数据库中执行)。想象一下,尝试从包含十亿行的表中获取单行,然后将所有行都提取出来然后只选择一个(如果不小心将 IQueryable 转换为 IEnumerable 并延迟加载相关数据,情况会变得更糟)。

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

【讨论】:

不支持==真的很奇怪。无论如何,感谢i.ID.Equals(someId) 的回答对我来说很好。【参考方案2】:

这对我有用 -

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

【讨论】:

不幸的是,执行上述操作会出现问题 - social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/… 在该页面底部的 MS Connect 中记录了一个错误链接。希望你们中的一些人可以投票,这样它就可以被查看 - 这是一个让我烦恼一段时间的问题......【参考方案3】:

试试这个:

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;      
        
 

【讨论】:

【参考方案4】:

为了将您的 LINQ 查询转换为实际的 SQL,Linq2SQL 会检查您给它的表达式。问题是您没有为 L2S 提供足够的信息,无法将“ID”属性转换为实际的数据库列名。您可以通过确保 L2S 可以将“ID”映射到“IDField”来实现您想要的。

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

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

public partial class MyEntity: IEntity 
    

【讨论】:

以上是关于LINQ,在映射中实现接口和异常的实体的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis映射实体改造和异常问题

不支持接口映射,但Linq-Sql对象已经实现了属性

错误 3002:映射片段中的问题 | c# linq 到实体

LinQ to SQL 查询

关于 Linq 到 SQL 映射对象设计的建议

休眠映射异常:实体映射中的重复列