Как исправить ошибку: «Указанный тип элемента не поддерживается в LINQ to Entities ...» в не отображенных столбцах - PullRequest
0 голосов
/ 31 декабря 2018

Таблица 1:

class TRD
{
    [Column("ID")]
    [Key]
    [Required]
    public int ID { set; get; }

    [Column("Name", TypeName = "nvarchar")]
    public string Name { set; get; }    // <-- Mapped 

    [Column("LastName", TypeName = "nvarchar")]
    public string LastName { set; get; }    // <-- Mapped 

    public string DisplayFullName    // <-- Not Mapped
    {
        get
        {
            return string.Format("{0} - {1}", Name, LastName);
        }
    } 
    [Column("gate_id", TypeName = "int")]
    public int gate_id { get; set; }   // <-- Mapped - foreign key
}

Таблица 2:

class Gate
{
    [Column("ID")]
    [Key]
    [Required]
    public int ID { set; get; } 
    public string name { get; set; }
}

Я хочу, чтобы TRD оставил присоединение Gate:

var search = OdataBaseContex.TRD.GroupJoin(
        OdataBaseContex.Gates,
        f => f.gate_id,
        p => p.ID,
        (x, y) => new { TRD = x, gate = y })
.SelectMany(
        x => x.gate.DefaultIfEmpty(),
        (x, y) => new {
            LastName = x.TRD.LastName,
            Name = x.TRD.Name,
            DisplayFullName = x.TRD.DisplayFullName,  //<-- Error 
            gate_id = y.name
        }).ToList(); 

Ошибка:

Указанный элемент типа 'DisplayFullName' не поддерживается в LINQ to Entities.Поддерживаются только инициализаторы, элементы сущностей и свойства навигации сущностей.

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Ваш запрос не будет работать, так как этот запрос преобразуется в запрос SQL, и в этот раз он не понимает, что вы использовали в установщике в классе .Net.Итак, попробуйте использовать выражения, иначе другие обходные пути уже перечислены выше, я думаю, что это будет работать для вас.

0 голосов
/ 31 декабря 2018

Попробуйте:

var search = OdataBaseContex.TRD.GroupJoin(
        OdataBaseContex.Gates,
        f => f.gate_id,
        p => p.ID,
        (x, y) => new { TRD = x, gate = y })
.SelectMany(
        x => x.gate.DefaultIfEmpty(),
        (x, y) => new {
            LastName = x.TRD.LastName,
            Name = x.TRD.Name,
            DisplayFullName = x.TRD.Name+"-"+x.TRD.LastName,   
            gate_id = y.name
        }).ToList(); 

или не используйте это свойство string.Format как x.TRD.Name+"-"+x.TRD.LastName:

public string DisplayFullName
{
    get
    {
        return Name + " - " + LastName;
    }
}

ОБНОВЛЕНИЕ:
как мой комментарий ниже, когда вы хотите использовать метод в Linq-To-Entities запросе, он превращает запрос в исполняемый запрос для базы данных, поэтому при вызове вашего метода в C # будет преобразован в некоторый SQL-запрос, так что если всеC # на самом деле выполняется как SQL, нет проблем, иначе вы не можете вызвать method() в основном блоке запроса, кстати, временное решение и простое решение - разделить этот запрос на отдельные части, как показано ниже:

var search = OdataBaseContex.TRD.GroupJoin(
        OdataBaseContex.Gates,
        f => f.gate_id,
        p => p.ID,
        (x, y) => new { TRD = x, gate = y })
.SelectMany(
        x => x.gate.DefaultIfEmpty(),
        (x, y) => new
        {
            LastName = x.TRD.LastName,
            Name = x.TRD.Name, 
            gate_id = y.name
        }).ToList().Select(mn => new
        {
            LastName = mn.LastName,
            Name = mn.Name,
            DisplayFullName = GetFullName(mn.Name,mn.LastName)
            gate_id = mn.gate_id
        });

, вызвав ToList(), ваш запрос будет выполнен в БД, а затем к последнему Select() вы получите то, что хотите.
Или предположим, что у вас есть класс DTO, как показано ниже:

public class DtoClass
{ 
    public string FullName { get; set; }
    public int GateId { get; set; }
    public string ShamsiDate { get; set; }
}

тогда вы можете выполнить запрос в два шага:

var search = OdataBaseContex.TRD.GroupJoin(
        OdataBaseContex.Gates,
        f => f.gate_id,
        p => p.ID,
        (x, y) => new { TRD = x, gate = y })
.SelectMany(
        x => x.gate.DefaultIfEmpty(),
        (x, y) => new
        {
            LastName = x.TRD.LastName,
            Name = x.TRD.Name,
            gate_id = y.name
        }).ToList();//query will be executed on DB because of ToList()
List<DtoClass> results = search.Select(mn =>
        {
            //Manipulating mn data 
            //call some custom method to cast Date
            string newDate = CastMiladi2Other(date);
            DtoClass ret = new DtoClass()
            { 
                FullName = GetFullName(mn.Name, mn.LastName),
                ShamsiDate = newDate,
                GateId = mn.gate_id
            };
            return ret;
        }).ToList();

в Select() из results вы можете делать и вызывать любые методы, которые вы хотите, вы также можете использовать AsEnumerable() вместо ToList(), остальная часть запроса будет затем оценена как коллекция в памяти, используяLinq-to-Objects.

...