我在LINQ中使用存储库模式,具有IRepository.DeleteOnSubmit(T Entity)。 它工作正常,但是当我的实体类具有接口时,如下所示:
1 2 3 4 5 6 7 8 9
| public interface IEntity { int ID {get;set;} }
public partial class MyEntity: IEntity {
public int ID {
get { return this.IDfield; }
set { this.IDfield=value; }
}
} |
然后尝试删除一些这样的实体:
1 2
| IEntity ie=repository.GetByID(1);
repoitory.DeleteOnSubmit(ie); |
抛出
成员" IEntity.ID"不支持对SQL的转换。
从数据库中获取数据有效,但删除和插入无效。 如何对DataContext使用接口?
这里是:
异常消息:
成员'MMRI.DAL.ITag.idContent'没有支持的SQL转换。
码:
1 2 3 4
| var d = repContent.GetAll().Where(x => x.idContent.Equals(idContent));
foreach (var tagConnect in d) <- error line
{
repContet.DeleteOnSubmit(tagConnect); |
(它从数据库获取所有标签,并删除它们)
和堆栈跟踪:
1 2 3 4 5 6 7 8 9 10 11 12
| [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( ... |
当我尝试装饰局部类时:
1 2 3
| [Column(Storage ="_idEvent", DbType ="Int NOT NULL", IsPrimaryKey = true)]
public int idContent
{ get { return this.idEvent; } set { this.idEvent=value; } } |
它会引发错误"无效的列名'idContent'。"
当在MVC4中使用linq-to-sql时,Microsoft似乎放弃了对接口中==运算符的支持(或者可能从不支持)。但是,您可以使用i.ID.Equals(someId)代替==运算符。
将IQueryable强制转换为IEnumerable是可行的,但不应使用!原因是:IQueryable具有IEnumerable的时髦实现。无论您通过IEnumerable接口在IQueryable上使用哪种linq方法,都会导致首先执行查询,将所有结果从DB提取到内存中,并最终在数据上本地运行该方法(通常是那些方法将转换为SQL并在数据库中执行)。想象一下,试图从包含数十亿行的表中获取一行,然后只提取所有行以选择其中的一个(而且,如果不小心将IQueryable强制转换为IEnumerable并延迟加载相关数据,情况会更糟)。
显然,Linq在本地数据接口上使用==运算符(因此仅影响IQueryable)以及实体框架(或我听说)都没有问题。
这对我有用-
1 2 3 4 5 6 7 8
| public partial class MyEntity: IEntity
{ [Column(Name ="IDfield", Storage ="_IDfield", IsDbGenerated = true)]
public int ID
{
get { return this.IDfield; }
set { this.IDfield=value; }
}
} |
为了将LINQ查询转换为实际的SQL,Linq2SQL会检查您提供的表达式。问题是您没有为L2S提供足够的信息以将" ID"属性转换为实际的DB列名称。您可以通过确保L2S可以将" ID"映射到" IDField"来实现所需的功能。
使用答案中提供的方法应该可以做到这一点。
如果使用设计器,还可以简单地将类属性" IDField"重命名为" ID",其好处是您不必再在分部类(即分部类)中显式实现" ID"属性。 MyEntity的定义变成:
1 2 3
| public partial class MyEntity: IEntity
{
} |
试试这个:
1 2 3 4 5 6 7 8 9 10
| 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; }
}
} |