Spent huge of time but do not understand why .Include(t => t.Nodes)
does not return any Node entities:
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;
}
}
The row below
var tree = dataBaseContext.Tree.Include(t => t.Nodes).SingleOrDefault(t => t.Name == name)
initialize .Include(t => t.Nodes)
.Include(t => t.Nodes)
should return nodes entities if they exist
Attach addititonal code
DataBaseContext.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");
}
}
}
NodeTable.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; }
}
}
TreeTable.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; }
}
}
Startup.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();
});
}
}
}
Resolved! I used the old library System.Data.Entity
. Replaced it with Microsoft.EntityFrameworkCore
and Include
method started working correctly.