使用 CSharpCodeProvider 生成 DbContext

Generate DbContext using CSharpCodeProvider

使用下面的代码我在 运行 时间

生成 OnlineShopContext
           string code = @"
           using System.Data.Entity;
           using GenerateContext.Models;
           using System.Data.Entity.Core.EntityClient;
           using GenerateContext.Models.Mapping;

           namespace GenerateContext.Models
           {
public partial class OnlineShopContext : DbContext
{
    static OnlineShopContext()
    {
        Database.SetInitializer<OnlineShopContext>(null);
    }

    public OnlineShopContext()
        : base(""Name = OnlineShopContext"")
    {
        }

  public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }
    public DbSet<OrderItem> OrderItems { get; set; }
    public DbSet<Product> Products { get; set; }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new CustomerMap());
        modelBuilder.Configurations.Add(new OrderMap());
        modelBuilder.Configurations.Add(new OrderItemMap());
        modelBuilder.Configurations.Add(new ProductMap());
    }

}
}
";

        CSharpCodeProvider provider = new CSharpCodeProvider();
        CompilerParameters parameters = new CompilerParameters();

        // Reference to System.Drawing library
        parameters.ReferencedAssemblies.Add("System.Drawing.dll");
        parameters.ReferencedAssemblies.Add("System.Data.dll");
        parameters.ReferencedAssemblies.Add("System.Data.Entity.dll");
        parameters.ReferencedAssemblies.Add("System.ComponentModel.dll");
      parameters.ReferencedAssemblies.Add(typeof(Customer).Assembly.Location);
                       parameters.ReferencedAssemblies.Add(typeof(CustomerMap).Assembly.Location);
                       parameters.ReferencedAssemblies.Add(typeof(DbSet).Assembly.Location);
                       parameters.ReferencedAssemblies.Add(typeof(DbContext).Assembly.Location);
                       parameters.ReferencedAssemblies.Add(typeof(IQueryable).Assembly.Location);
                                      parameters.ReferencedAssemblies.Add(typeof(IQueryable<>).Assembly.Location);
                       parameters.ReferencedAssemblies.Add(typeof(System.ComponentModel.IListSource).Assembly.Location);

        parameters.GenerateExecutable = false;
        parameters.GenerateInMemory = false;
        parameters.OutputAssembly = "OutputAssembly.dll";

        CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);

        if (results.Errors.HasErrors)
        {
            StringBuilder sb = new StringBuilder();

            foreach (CompilerError error in results.Errors)
            {
                sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
            }

            throw new InvalidOperationException(sb.ToString());
        }

生成的程序集是:(使用 ILSpy)

using GenerateContext.Models.Mapping;
using System;
using System.Data.Entity;

namespace GenerateContext.Models
{
public class OnlineShopContext : DbContext
{
    public DbSet<Customer> Customers
    {
        get;
        set;
    }

    public DbSet<Order> Orders
    {
        get;
        set;
    }

    public DbSet<OrderItem> OrderItems
    {
        get;
        set;
    }

    public DbSet<Product> Products
    {
        get;
        set;
    }

    static OnlineShopContext()
    {
        Database.SetInitializer<OnlineShopContext>(null);
    }

    public OnlineShopContext() : base("Name = OnlineShopContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add<Customer>(new CustomerMap());
        modelBuilder.Configurations.Add<Order>(new OrderMap());
        modelBuilder.Configurations.Add<OrderItem>(new OrderItemMap());
        modelBuilder.Configurations.Add<Product>(new ProductMap());
    }
}

}

当我想创建实例和 运行 查询(例如 FirstOrDeafult 或 Where)时,这些方法不存在。但是有一个 Find 方法没有 运行 因为不匹配的数据类型很奇怪

        Assembly assembly = results.CompiledAssembly;
        Type type = assembly.GetType("GenerateContext.Models.OnlineShopContext");
        dynamic db = (DbContext)Activator.CreateInstance(type);
        var obj = db.Customers.GetType();
        MethodInfo main = obj.GetMethod("Find");
        object[] parametersArray = new object[] { 100 };
        var customer = main.Invoke(obj, parametersArray);

我该怎么做? 如何将实例转换为类型并使用它强类型以使用 Where 或 FirstOrDefault

获取数据

如果我将 db.Customers 转换为 System.Data.Entity.DbSet<Customer> 它会起作用。如下图

        var dllversionAssm = Assembly.LoadFile(@debugPath+"OutputAssembly.dll");
        Type type = dllversionAssm.GetType("GenerateContext.Models.OnlineShopContext");
        dynamic db = (DbContext)Activator.CreateInstance(type);
        var customerService  = ((System.Data.Entity.DbSet<Customer>)db.Customers);
        var customer = customerService.FirstOrDefault(q => q.Id == 100);

现在,我如何将任何动态类型转换为其实体类型,例如 db.Orders 转换为 System.Data.Entity.DbSet<Order> 或 db.Products 转换为 System.Data.Entity.DbSet<Product> 。我的意思是我怎样才能有一个通用的方法来做到这一点?

我终于做到了。

    public System.Data.Entity.DbSet<T> Get<T>() where T : class
    {
        var dllversionAssm = Assembly.LoadFile(debugPath+"OutputAssembly.dll");
        Type type = dllversionAssm.GetType("GenerateContext.Models.OnlineShopContext");
        DbContext db = (DbContext)Activator.CreateInstance(type);
        var set = db.Set<T>();
        return set;
    }