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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-01 08:47:32  来源:igfitidea点击:

LINQ, entity that implements Interface and exception in mapping

提问by Hrvoje Hudo

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

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

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.

throws
成员“IEntity.ID”不支持转换为 SQL。

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

从数据库中获取数据有效,但删除和插入无效。如何针对 DataContext 使用接口?



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

它是:
异常消息:成员“MMRI.DAL.ITag.idContent”不支持转换为 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'."

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

回答by Mark Cidade

Try this:

尝试这个:

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

回答by Frank Tzanabetis

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

回答by jeroenh

For translating your LINQ query to actual SQL, Linq2SQL inspects the expression you give it. The problem is that you have not supplied enough information for L2S to be able to translate the "ID" property to the actual DB column name. You can achieve what you want by making sure that L2S can map "ID" to "IDField".

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

This should be possible using the approach provided in answers.

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

If you use the designer, you can also simply rename the class property "IDField" to "ID", with the added benefit that you won't have to explicitly implement the "ID" property in your partial class anymore, i.e. the partial class definition for MyEntity simply becomes:

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

public partial class MyEntity: IEntity 
{    
}

回答by jahu

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.

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

Casting IQueryableto IEnumerableworks but should not be used!The reason is: IQueryablehas funky implementation of IEnumerable. Whatever linq method you'll use on a IQueryablethrough the IEnumerableinterface 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 IQueryableto IEnumerableand lazy loading related data).

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

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

显然,Linq==在本地数据上使用带有接口的操作符(所以只IQueryable受影响)和实体框架(或者我听说过)没有问题。