LINQ, сущность, которая реализует интерфейс и исключение в отображении - PullRequest
9 голосов
/ 18 августа 2008

Я использую шаблон репозитория с 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 ».»

Ответы [ 4 ]

7 голосов
/ 15 декабря 2014

Похоже, Microsoft отказалась от поддержки оператора == в интерфейсах при использовании linq-to-sql в MVC4 (или, возможно, это никогда не поддерживалось). Однако вы можете использовать i.ID.Equals(someId) вместо оператора ==.

Приведение IQueryable к IEnumerable работает, но не должно использоваться! Причина: IQueryable имеет классную реализацию IEnumerable. Какой бы метод linq вы не использовали в IQueryable через интерфейс IEnumerable, сначала будет выполняться запрос, все результаты извлекаются из памяти в БД и, в конце концов, запускаются методом локально для данных (обычно это методы будут переведены в SQL и выполнены в БД). Представьте себе, что вы пытаетесь получить одну строку из таблицы, содержащей миллиард строк, выбирая все из них, чтобы выбрать только одну (и это становится намного хуже при неосторожном приведении IQueryable к IEnumerable и отложенной загрузке данных).

Очевидно, у Linq нет проблем с использованием оператора == с интерфейсами на локальных данных (поэтому затрагивается только IQueryable), а также с Entity Frameworks (или, как я слышал).

3 голосов
/ 15 января 2010

Это работает для меня -

public partial class MyEntity: IEntity 
 {    [Column(Name = "IDfield", Storage = "_IDfield", IsDbGenerated = true)]
      public int ID 
       {         
          get { return this.IDfield; }        
          set { this.IDfield=value;  }    
       } 
 }
0 голосов
/ 15 января 2010

Для перевода вашего запроса LINQ в реальный SQL, Linq2SQL проверяет выражение, которое вы ему даете. Проблема в том, что вы не предоставили достаточно информации для L2S, чтобы иметь возможность преобразовать свойство «ID» в фактическое имя столбца БД. Вы можете достичь того, чего хотите, убедившись, что L2S может сопоставить «ID» с «IDField».

Это должно быть возможно с использованием подхода, представленного в ответах.

Если вы используете конструктор, вы также можете просто переименовать свойство класса «IDField» в «ID», с дополнительным преимуществом, что вам больше не придется явно реализовывать свойство «ID» в вашем частичном классе, т.е. частичное определение класса для MyEntity просто становится:

public partial class MyEntity: IEntity 
{    
}
0 голосов
/ 18 августа 2008

Попробуйте это:

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;  }    
       } 
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...