EF LINQ метод для связанных объектов - PullRequest
0 голосов
/ 27 марта 2020

Я пытаюсь написать запрос LINQ, используя методы расширения сначала с кодом EF, чтобы пройти через 3 связанных объекта. Сущности CpeDefinition и PaperMachine имеют много-много связей с сущностью Tag.

У меня есть 2 ввода c для этого запроса, 1 для Cpe Id и еще одно имя тега.

I Я хочу получить запись CpeDefinition для выбранного пользователем идентификатора, затем для этой записи Cpe я хочу получить все соответствующие теги, сопоставленные с этим Cpe, а затем отфильтровать эти результирующие теги по имени введенного пользователем тега плюс двоеточие. Наконец, из этих полученных тегов я хочу получить сопоставление записей PaperMachine с этими тегами.


    public class Tag {
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<CpeDefinition> CpeDefinitions { get; set; }
        public virtual ICollection<PaperMachine> PaperMachines { get; set; }        
    }

    public class CpeDefinition
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public virtual ICollection<Tag> Tags { get; set; }
    }

    public class PaperMachine
    {
        public int Id { get; set; }
        public string Type { get; set; }
        public string Plant { get; set; }
        public string Line { get; set; }
        public virtual ICollection<Tag> Tags { get; set; }
    }

    modelBuilder.Entity<PaperMachine>()
                .HasMany<Tag>(p => p.Tags)
                .WithMany(t => t.PaperMachines)
                .Map(pt => {
                    pt.MapLeftKey("PaperMachineId");
                    pt.MapRightKey("TagId");
                    pt.ToTable("PaperMachinesTags");
                });

    modelBuilder.Entity<CpeDefinition>()
                .HasMany<Tag>(d => d.Tags)
                .WithMany(t => t.CpeDefinitions)
                .Map(dt => {
                    dt.MapLeftKey("CpeDefinitionId");
                    dt.MapRightKey("TagId");
                    dt.ToTable("CpeDefinitionsTags");

Изначально у меня был этот запрос, который почти меня туда доставил, но он не фильтрует теги по соответствующим CpeDefinition (он возвращает все бумажные машины, которые соответствуют введенному пользователем тегу, но не выбранному пользователем Cpe:

string tag = "SiteA";

var taggedPaperMachines = db.Tags
    .Where(t => t.Name.Contains(String.Concat(tag, ":")))
    .Select(p => new
    {
        p.PaperMachines.FirstOrDefault().Id,
        p.PaperMachines.FirstOrDefault().Line,
        p.PaperMachines.FirstOrDefault().Plant,
        p.PaperMachines.FirstOrDefault().Type
    }).ToList()
    .Select(pm => new PaperMachine
    {
        Id = pm.Id,
        Line = pm.Line,
        Plant = pm.Plant,
        Type = pm.Type
    });  

Я пытался собрать Cpe и теги вместе, но я получаю нулевую ошибку, которую я не понимаю, почему, поскольку я знаю, что в таблице базы данных есть Cpe с Id = 1:

Ошибка приведения к типу значения 'System.Int32', поскольку материализованное значение равно нулю. c параметр или запрос должен использовать обнуляемый тип

int CpeId = 1;
string TagName = "SiteA";

var temp1 = db.CpeDefinitions
    .Where(cd => cd.Id == CpeId)
    .Select(cd => new
    {
        cd.Tags.FirstOrDefault().Id,
        cd.Tags.FirstOrDefault().Name
    }) 
    .ToList()
    .Select(t => new Tag
    {
        Id = t.Id,
        Name = t.Name
    });    

В идеальном мире мне бы хотелось, чтобы все эти логи c были обернуты в один запрос, но на этом этапе не возражаю взять результаты 2-го запроса и вставить их в 1-й запрос.

1 Ответ

1 голос
/ 27 марта 2020

Очень просто:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DataBase db = new DataBase();
            string tag = "SiteA";

            var query = (from t in db.Tags
                         join c in db.CpeDefinitions on t.Id equals c.Id
                         select new { tag = t, definition = c }
                        ).ToList();

            List<PaperMachine> paperMachines = query.Where(x => x.tag.Name == (tag + ":"))
                .SelectMany(x => x.tag.PaperMachines).ToList(); 

        }
    }
    public class DataBase
    {
        public List<Tag> Tags { get; set; }
        public List<CpeDefinition> CpeDefinitions { get; set; }
        public List<PaperMachine> PaperMachines { get; set; }
    }
    public class Tag
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<CpeDefinition> CpeDefinitions { get; set; }
        public virtual ICollection<PaperMachine> PaperMachines { get; set; }
    }

    public class CpeDefinition
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public virtual ICollection<Tag> Tags { get; set; }
    }

    public class PaperMachine
    {
        public int Id { get; set; }
        public string Type { get; set; }
        public string Plant { get; set; }
        public string Line { get; set; }
        public virtual ICollection<Tag> Tags { get; set; }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...