动态创建模型

Izz*_*zzy 9 c# asp.net asp.net-mvc entity-framework winforms

每次传入连接字符串时,是否可以使用实体框架动态创建整个模型(数据库优先)方法?

我尝试了以下方法:

MetaModel model = new MetaModel();
model.RegisterContext(() => new Model1(connectionString),
new ContextConfiguration()
 {
  ScaffoldAllTables = true
 });
Run Code Online (Sandbox Code Playgroud)

但它一直在给我一个错误

System.Web.DynamicData.dll中发生了未处理的"System.ArgumentException"类型异常

附加信息:不支持上下文类型"DbContext.Model1".

更多信息:

我拥有数据库中所有必需的表,我无法控制,如果我需要旧表中的任何新表或列,那么db人员会为我运行相应的脚本.

我正在尝试创建一个通用的DLL EF,我可以使用它在各种应用程序6,包括winformsmvcWeb应用程序.我想弄清楚我们最好的方法是什么.

我可以混合codefirstdatabasefirst在一起?

不会codefirst为我生成我已经拥有的表格吗?

我的每个应用程序都包含1个winforms和1个Web应用程序,并且它们共享数据源,例如

测试1 Windows App&Test 1 MVC App = DB 1

测试2 Windows App&Test 2 MVC App = DB 2

测试3 Windows App&Test 3 MVC App = DB 3

所以我需要传递connectionstringDBContext.我的实体将如何运作?

如果需要更多信息,请告诉我.

Rez*_*aei 3

从技术上讲,您可以在运行时创建实体框架模型,至少可以通过动态创建程序集并使用代码首先起作用的 API 和属性,或者为模型创建所需的 xml 来创建。您不需要在运行时创建模型类。

事实上,在运行时创建模型类是没有用的,因为您创建的模型可以在编译时和运行时键入工作。您创建模型是因为您想要将 a 传递Type1给方法或编写此类类型查询,例如.Where(x=>x.SomeFiled == SomeValue)

如果您针对不同的客户有不同的应用程序实例

如果您为不同的客户有不同的应用程序实例,则无需执行任何特定操作。您的应用程序已编写为可供使用,只需在不同的客户中使用不同的连接字符串webconfig即可appconfig

如果您有一个适用于所有客户的应用程序实例

在这种情况下,如果您有一个多租户应用程序,您可以简单地向接受连接字符串作为输入的数据库上下文构造函数添加一个重载。然后,当您需要创建数据库上下文的实例时,您可以使用该重载并根据租户检测策略在连接字符串中注入合适的用户名、密码和数据库名称。

public partial class SampleDbEntities
{
    public SampleDbEntities(string connectionString) : base(connectionString)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

最好将新的重载放在分部类中。这样每次更新上下文运行的模板时就不会被edmx触及.tt

例如,您可以通过以下方式创建连接字符串和上下文:

var connectionTemplate =
    @"metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;" +
    @"provider=System.Data.SqlClient;" +
    @"provider connection string=""data source={0};" +
    @"initial catalog={1};" +
    @"persist security info=True;" +
    @"user id={2};" +
    @"password={3};" +  
    @"MultipleActiveResultSets=True;App=EntityFramework""";

string connection = string.Format(connectionTemplate, 
    @"(localdb)\v11.0", @"SampleDB1", @"user1" , @"password1");

var db = new SampleDbEntities(connection);
Run Code Online (Sandbox Code Playgroud)

或者您可能需要 Windows 身份验证,然后使用@"integrated security=True;" +.

您可以根据不同的策略检测不同的租户,包括:

  • 应用程序 URL(域和子域)
  • 查询字符串或路由值
  • 用户名

您可以将创建合适上下文的角色赋予基于您的租户策略的类。

如果数据库中的表发生变化,我该怎么办?

只需在设计时更新您的 edmx 模型并重建您的应用程序并重新分发它。如上所述,如果一个字段添加到表中或一个新表添加到数据库中,并且您想在应用程序中编写此类类型的查询db.Tabe1.Where(x=>x.Field1==value1),那么您需要从数据库更新模型并重建您的应用程序。在运行时重新生成模型没有意义。

我怎样才能提高生产力?

我知道您的目标是提高生产力,但在运行时生成模型并不是您想要的。相反,您可以创建一些通用数据访问层和通用业务逻辑层来提高生产力。例如,如果您有很多需要 CRUD 操作的实体,您可以创建一个EntityBusiness<TContext, TModel>类并拥有泛型void Create(TModel entity)IList<TModel> GetAll(object key)TModel GetByKey(object key)TModel Update(TModel entity)void DeleteByKey(object key)等。这样您就可以简单地创建它的实例EntityBusiness<SampleDbEntities, Product>或继承它。该类包含简单 CRUD 操作的所有行为,您可以通过添加对其他一些有用案例(例如验证)的支持来增强它。作为创建通用存储库和工作单元的示例,请查看ASP.NET MVC 站点中的这篇文章。