Метод EntityFramework Include не работает

Потратил кучу времени, но не понимаю, почему .Include(t => t.Nodes) не возвращает объекты Node:

public class TreeRepository : ITreeRepository
{
    private DataBaseContext dataBaseContext;

    public TreeRepository(DataBaseContext dataBaseContext)
    {
        this.dataBaseContext = dataBaseContext;
    }

    public async Task<ITree> GetTreeAsync(string name)
    {
        var tree = dataBaseContext.Tree.Include(t => t.Nodes).SingleOrDefault(t => t.Name == name);

        if (tree == null)
        {
            var t = await dataBaseContext.Tree.AddAsync(new TreeTable { Name = name });
            await dataBaseContext.SaveChangesAsync();

            tree = t.Entity;
        }

        return tree;
    }
}

Строка ниже

var tree = dataBaseContext.Tree.Include(t => t.Nodes).SingleOrDefault(t => t.Name == name)

инициализировать .Include(t => t.Nodes)

Узлы пусты

Узлы заполнены

.Include(t => t.Nodes) должен возвращать объекты узлов, если они существуют

Прикрепите дополнительный код

Контекст базы данных.cs

using Microsoft.EntityFrameworkCore;
using FxNet.Web.Def.Api.Diagnostic.DAL.Db.Tables;

namespace FxNet.Web.Def.Api.Diagnostic.DAL.Db
{
    public class DataBaseContext : DbContext
    {
        public DataBaseContext(DbContextOptions<DataBaseContext> options) : base(options) {}

        public DbSet<JournalTable> Journal { get; set; }
        public DbSet<NodeTable> Node { get; set; }
        public DbSet<TreeTable> Tree { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<TreeTable>().ToTable("Tree"); //.Navigation(e => e.Nodes).AutoInclude();
            modelBuilder.Entity<NodeTable>().ToTable("Node");
            modelBuilder.Entity<JournalTable>().ToTable("Journal");
        }
    }
}

Нодетабле.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using FxNet.Web.Def.Api.Diagnostic.DAL.Infrastructure.Entity;

namespace FxNet.Web.Def.Api.Diagnostic.DAL.Db.Tables
{
    [Table("Node")]
    public class NodeTable : INode
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long Id { get; set; }

        public long TreeId { get; set; }

        [ForeignKey("TreeId")]
        public virtual TreeTable Tree { get; set; }

        public long ParentNodeId { get; set; }

        public string Name { get; set; }
    }
}

Древетабле.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using FxNet.Web.Def.Api.Diagnostic.DAL.Infrastructure.Entity;

namespace FxNet.Web.Def.Api.Diagnostic.DAL.Db.Tables
{
    [Table("Tree")]
    public class TreeTable : ITree
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long Id { get; set; }

        public string Name { get; set; }

        IEnumerable<INode> ITree.Nodes => Nodes;

        public virtual List<NodeTable> Nodes { get; set; }
    }
}

INode.cs

namespace FxNet.Web.Def.Api.Diagnostic.DAL.Infrastructure.Entity
{
    public interface INode
    {
        long Id { get; set; }

        long TreeId { get; set; }

        long ParentNodeId { get; set; }

        string Name { get; set; }
    }
}

ITree.cs

namespace FxNet.Web.Def.Api.Diagnostic.DAL.Infrastructure.Entity
{
    public interface ITree
    {
        long Id { get; set; }

        string Name { get; set; }

        IEnumerable<INode> Nodes { get; }
    }
}

Стартап.cs

using System.Linq;
using System.Reflection;
using System.ComponentModel;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using FxNet.Web.Def.Api.Diagnostic.DAL.Db;
using FxNet.Web.Def.Api.Diagnostic.Middleware;
using Microsoft.Extensions.DependencyInjection;
using FxNet.Web.Def.Api.Diagnostic.DAL.Repository;
using FxNet.Web.Def.Api.Diagnostic.DAL.Infrastructure.Repository;

namespace FxNet.Web.Def.Api.Diagnostic
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddTransient<GlobalExceptionHandlerMiddleware>();
            services.AddSwaggerGen(c =>
            {
                c.CustomSchemaIds(x => x.GetCustomAttributes<DisplayNameAttribute>().SingleOrDefault()?.DisplayName ?? x.FullName);
            });

            services.AddTransient<IJournalRepository, JournalRepository>();
            services.AddTransient<INodeRepository, NodeRepository>();
            services.AddTransient<ITreeRepository, TreeRepository>();

            services.AddDbContext<DataBaseContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DataBaseConnectionString")));

            //services.AddDbContext<DataBaseContext>(options => options.UseNpgsql(Configuration.GetConnectionString("PostgreSQLConnectionString")));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "FxNet.Web.Def.Api.Diagnostic v1"));
            }

            using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetRequiredService<DataBaseContext>();
                context.Database.EnsureCreated();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

Я не уверен, правильно ли я понимаю ваш вопрос. .Include() не меняет значение, возвращаемое запросом. Он автоматически загружает указанные свойства навигации с использованием одного и того же запроса, что потенциально позволяет сократить количество обращений к базе данных. https://learn.microsoft.com/en-us/ef/core/querying/related-d‌​ata/eager

treterelda 14.08.2024 09:29

Как я обнаружил Learn.microsoft.com/en-us/ef/core/dbcontext-configuration, мы можем упростить конструкцию using инициализации dbContext в каждой функции (например, using (var context = new BloggingContext())). И это работает нормально, за исключением .Include()

Pavel Zazulia 14.08.2024 11:02

Добавлены ключевые классы и интерфейсы, SQL проверит. Спасибо

Pavel Zazulia 14.08.2024 11:52

SQL-запрос выглядит следующим образом: exec sp_executesql N'SELECT TOP(2) [t].[Id], [t].[Name] FROM [Tree] AS [t] WHERE [t].[Name] = @__name_0', N'@__name_0 nvarchar(4000)',@__name_0=N'Root1'. Никаких дополнительных подзапросов при вызове первой строки.

Pavel Zazulia 14.08.2024 12:29

То же самое, Узлы пусты. Я также попытался переименовать свойство Nodes интерфейса.

Pavel Zazulia 14.08.2024 13:24

Решено, я использовал System.Data.Entity в TreeRepository, изменился на Microsoft.EntityFrameworkCore, и все заработало. Магия

Pavel Zazulia 14.08.2024 13:59
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
93
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решено! Я использовал старую библиотеку System.Data.Entity. Заменил его на Microsoft.EntityFrameworkCore, и метод Include начал работать правильно.

Вы должны отметить это как ответ.

Astrid E. 14.08.2024 15:00

Другие вопросы по теме