c# - 即时创建模型

标签 c# asp.net asp.net-mvc winforms entity-framework

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

我尝试了以下方法:

MetaModel model = new MetaModel();
model.RegisterContext(() => new Model1(connectionString),
new ContextConfiguration()
 {
  ScaffoldAllTables = true
 });

但它总是给我一个错误

An unhandled exception of type 'System.ArgumentException' occurred in System.Web.DynamicData.dll

Additional information: The context type 'DbContext.Model1' is not supported.

更多信息:

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

我正在尝试使用 EF 创建一个通用 DLL,我可以在各种应用程序 6 上使用它,包括 winformsmvc 网络应用程序。我正在尝试找出解决此问题的最佳方法。

我可以将 codefirstdatabasefirst 混合在一起吗?

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

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

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

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

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

所以我需要将 connectionstring 传递给 DBContext。我的实体将如何工作?

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

最佳答案

技术上,您可以在运行时创建 Entity Framework 模型,至少通过动态创建程序集并使用代码首先工作的 api 和属性,或者通过创建模型所需的 xml。 但是您不需要在运行时创建模型类。

事实上,在运行时创建模型类是没有用的,因为您创建的模型在编译时和运行时都可以工作。你创建模型是因为你想传递 Type1到方法或编写类似 .Where(x=>x.SomeFiled == SomeValue) 的类型查询.

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

如果您为不同的客户提供不同的应用程序实例,则无需执行任何特定操作。您的应用程序已准备就绪,只需在 webconfig 中使用不同的连接字符串即可和 appconfig针对不同的客户。

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

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

public partial class SampleDbEntities
{
    public SampleDbEntities(string connectionString) : base(connectionString)
    {
    }
}

最好将新的重载放在分部类中。然后每次更新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);

或者您可能需要 Windows 身份验证,然后使用 @"integrated security=True;" + 代替用户 ID 和密码.

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

  • 申请网址(域和子域)
  • 查询字符串或路由值
  • 用户名

您可以将创建合适上下文的角色赋予根据您的租户策略工作的类。

数据库表发生变化怎么办?

只需在设计时更新您的 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 操作的所有行为,您可以通过添加对验证等其他一些有用案例的支持来增强它。作为创建通用存储库和工作单元的示例,请查看此 article在 asp.net mvc 站点中。

关于c# - 即时创建模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37945234/

相关文章:

c# - Raspberry Pi 上 Linux 环境中的 Windows Forms 错误

c# - Unity 广告的 resultCallback 仅在视频完成时奖励

c# - 如何从页面访问用户控件的值?

c# - 对齐 GridView 中的行值

c# - 从我的 asp.net mvc web 应用程序调用 asp.net 控制台应用程序

c# - 通过 LabelFor 的 DisplayName 文本,无需编码

c# - 在 ASP.NET MVC 中获取 MembershipUser

c# - 使用 Azure Read/OCR API 从 PDF 中提取复选框数据

c# - 禁用图像按钮上的回发单击 asp

c# - 将 jquery 添加到 Visual Studio 中的 "empty"Web 项目的最佳方法?