【问题标题】:Is there a way to dynamically add a DbSet to EF core and to use Linq against the dynamic DbSet?有没有办法将 DbSet 动态添加到 EF 核心并针对动态 DbSet 使用 Linq?
【发布时间】:2020-12-21 22:26:20
【问题描述】:

我正在使用 EF Core v. 5.0SQLite DB,我正在尝试将 DbSet 动态添加到我的 DbContext。我已经按照并重新改编了本指南以适应 EF Core:https://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/,并且我意识到了这个 DbContext 类

     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[] { });
                }
            }
        }
    }

我的“博客”和“文章”类:

    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”变量中,我可以看到使用 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(); 
            }
        }

至此,成功看到动态添加的“Article”类,但是使用Linq无法查询“Article”,当然,因为它在DbContext中并不存在.

有没有办法对动态 DbSet 添加的表(如“Article”)使用 Linq?

【问题讨论】:

  • 如果DbSet不存在,可以使用context.Set&lt;Entity&gt;()查询
  • @Yinqiu 谢谢你的回答。问题是 context.Set() 要求直接传递“Article”类,不能如我所愿动态传递,例如:object instantiatedObject = Activator.CreateInstance(objectType); context.Set&lt;instantiatedObject&gt;();

标签: .net-core entity-framework-core linq-to-entities dbset


【解决方案1】:

最后我使用“Linq.Dynamic.Core”解决了,它允许您使用 Linq 并将 lambda 表达式编写为字符串等等,here more info about Dynamic Linq

这里我如何修改之前显示的 TestMethod(),以及我如何对通过我的“GenericContextAppArticle”表进行查询/em>”类。

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;
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 2020-02-01
    • 1970-01-01
    • 2020-12-19
    • 2017-06-27
    • 1970-01-01
    • 2021-05-24
    相关资源
    最近更新 更多