有没有办法将 DbSet 动态添加到 EF 核心并对动态 DbSet 使用 Linq?
Is there a way to dynamically add a DbSet to EF core and to use Linq against the dynamic DbSet?
我正在使用 EF Core v. 5.0 和 SQLite DB 并且我正在尝试将 DbSet 动态添加到我的 DbContext .我已经遵循并重新改编了 EF Core 指南:https://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/ 并且我意识到了这一点 DbContext class:
internal class GenericAppContext : DbContext
{
public GenericAppContext()
{
//Disable the EF cache system to execute every running the OnModelCreating method.
//ATTENTION: This is a performance loss action!
this.ChangeTracker.LazyLoadingEnabled = false;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
//if "bin" is present, remove all the exceeding path starting from "bin" word
if (baseDir.Contains("bin"))
{
int index = baseDir.IndexOf("bin");
baseDir = baseDir.Substring(0, index);
}
options.UseSqlite($"Data Source={baseDir}Database\TestSQLite.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
MethodInfo addMethod = typeof(ModelBuilder).GetMethods().First(e => e.Name == "Entity");
foreach (var assembly in AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.GetName().Name != "EntityFramework"))
{
IEnumerable<Type> configTypes = assembly
.GetTypes()
.Where(t => t.BaseType != null
&& t.BaseType.IsGenericType
&& t.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in configTypes)
{
Type entityType = type.BaseType.GetGenericArguments().Single();
object entityConfig = assembly.CreateInstance(type.FullName);
addMethod?.MakeGenericMethod(entityType)
.Invoke(modelBuilder, new object[] { });
}
}
}
}
我的“博客”和“文章”classes:
internal class Blog : EntityTypeConfiguration<Blog>
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
}
internal class Article : EntityTypeConfiguration<Article>
{
[Key]
public int Id { get; set; }
public string Body { get; set; }
}
下面是我初始化 DbContext 的方式,在“tables”变量中我可以看到“文章”table 使用 context.Model.GetRelationalModel().Tables.ToList()
public static string TestMethod()
{
using (var context = new GenericAppContext())
{
string result = string.Empty;
//Ensures that the database for the context exists. If it exists, no action is taken. If it does not exist then the database and all its schema are created.
context.Database.EnsureCreated();
List<ITable> tables = context.Model.GetRelationalModel().Tables.ToList();
}
}
至此,我成功看到了动态添加的“文章”class,但是我无法使用Linq查询“文章”,当然,因为它在 DbContext 中不存在。
有没有办法针对添加的动态 DbSet 使用 Linq,如“文章”table?
最后 我使用“Linq.Dynamic.Core” 解决了问题,它允许您使用 Linq 并将 lambda 表达式写成字符串等等,here more info about Dynamic Linq.
这里是我如何修改之前显示的 TestMethod(),以及我如何针对“Article”进行查询 table 通过我的“GenericContextApp”class.
动态添加
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
public static string TestMethod()
{
using (var context = new GenericAppContext())
{
string result = string.Empty;
//Ensures that the database for the context exists. If it exists, no action is taken. If it does not exist then the database and all its schema are created.
context.Database.EnsureCreated();
IEnumerable<IEntityType> contextEntitiesList = context.Model.GetEntityTypes();
IQueryable<IEntityType> entitiesList = contextEntitiesList.Select(p => p).ToList().AsQueryable();
//Query against the dinamycally added "Article" table. It will return the SQL query as a string.
result = context.Query("Your.Complete.Namespace.Article").Where("Body == \"ciao\"").ToQueryString();
return result;
}
}
我正在使用 EF Core v. 5.0 和 SQLite DB 并且我正在尝试将 DbSet 动态添加到我的 DbContext .我已经遵循并重新改编了 EF Core 指南:https://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/ 并且我意识到了这一点 DbContext class:
internal class GenericAppContext : DbContext
{
public GenericAppContext()
{
//Disable the EF cache system to execute every running the OnModelCreating method.
//ATTENTION: This is a performance loss action!
this.ChangeTracker.LazyLoadingEnabled = false;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
//if "bin" is present, remove all the exceeding path starting from "bin" word
if (baseDir.Contains("bin"))
{
int index = baseDir.IndexOf("bin");
baseDir = baseDir.Substring(0, index);
}
options.UseSqlite($"Data Source={baseDir}Database\TestSQLite.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
MethodInfo addMethod = typeof(ModelBuilder).GetMethods().First(e => e.Name == "Entity");
foreach (var assembly in AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.GetName().Name != "EntityFramework"))
{
IEnumerable<Type> configTypes = assembly
.GetTypes()
.Where(t => t.BaseType != null
&& t.BaseType.IsGenericType
&& t.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in configTypes)
{
Type entityType = type.BaseType.GetGenericArguments().Single();
object entityConfig = assembly.CreateInstance(type.FullName);
addMethod?.MakeGenericMethod(entityType)
.Invoke(modelBuilder, new object[] { });
}
}
}
}
我的“博客”和“文章”classes:
internal class Blog : EntityTypeConfiguration<Blog>
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
}
internal class Article : EntityTypeConfiguration<Article>
{
[Key]
public int Id { get; set; }
public string Body { get; set; }
}
下面是我初始化 DbContext 的方式,在“tables”变量中我可以看到“文章”table 使用 context.Model.GetRelationalModel().Tables.ToList()
public static string TestMethod()
{
using (var context = new GenericAppContext())
{
string result = string.Empty;
//Ensures that the database for the context exists. If it exists, no action is taken. If it does not exist then the database and all its schema are created.
context.Database.EnsureCreated();
List<ITable> tables = context.Model.GetRelationalModel().Tables.ToList();
}
}
至此,我成功看到了动态添加的“文章”class,但是我无法使用Linq查询“文章”,当然,因为它在 DbContext 中不存在。
有没有办法针对添加的动态 DbSet 使用 Linq,如“文章”table?
最后 我使用“Linq.Dynamic.Core” 解决了问题,它允许您使用 Linq 并将 lambda 表达式写成字符串等等,here more info about Dynamic Linq.
这里是我如何修改之前显示的 TestMethod(),以及我如何针对“Article”进行查询 table 通过我的“GenericContextApp”class.
动态添加using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
public static string TestMethod()
{
using (var context = new GenericAppContext())
{
string result = string.Empty;
//Ensures that the database for the context exists. If it exists, no action is taken. If it does not exist then the database and all its schema are created.
context.Database.EnsureCreated();
IEnumerable<IEntityType> contextEntitiesList = context.Model.GetEntityTypes();
IQueryable<IEntityType> entitiesList = contextEntitiesList.Select(p => p).ToList().AsQueryable();
//Query against the dinamycally added "Article" table. It will return the SQL query as a string.
result = context.Query("Your.Complete.Namespace.Article").Where("Body == \"ciao\"").ToQueryString();
return result;
}
}