我来回搜索,但似乎无法得到我需要的东西。如果这个问题最近得到了回答,我感到很抱歉。重定向讨论对我有好处。
这是一个场景。我的老板指示我从Microsoft Visual Foxpro (MS将在2015年退出支持)转向。net c#。为了良好的基础和采用最佳实践,我决定先学习,将相关信息拼凑在一起,然后开始编码。这是第二年了。
我们是一家为50多家客户提供工资处理外包服务的公司。每个客户端目前都有自己的数据库。两个数据库的表结构完全相同。
我是一个新手。全新的。net世界我开始使用原始SQL使用数据表,数据阅读器,但在我的研究中,我得到了一些不鼓励这样做的讨论。许多人认为实体框架应该达到目的。但是可以混合使用各种方法,特别是在涉及复杂查询时。
有人能给我指出一些"好的阅读",我可以实现实体框架与50多个相同的数据库。每个数据库都是完全独立的,与其他数据库无关。当用户登录时,他们选择需要为哪个客户处理工资单,然后EF指向该数据库。
EF需要2条不同的信息来处理数据库中的数据:
1)数据库模式:这是作为编译代码包含在应用程序中,通常不能在运行时更改。
2)连接字符串:在运行时提供,通常来自配置文件。
在你的例子中,所有的数据库都有相同的模式,所以你可以只建模一个数据库,它将适用于所有其他的。
要更改的部分是连接字符串。这告诉EF如何查找数据库,可以在运行时提供。
DbContext
构造函数有一个过载,它接受一个连接字符串作为参数:MSDN: DbContext Constructor (String)
框架中甚至有类可以帮助你创建连接字符串:
MSDN: EntityConnectionStringBuilder Class
MSDN: Connection String Builders
很简单
,
//WMSEntities is conection string name in web.config
//also the name of Entitiframework
public WMSEntities() : base("name=WMSEntities")
{
}
已经在自动生成的Model.Context.cs中的edmx文件夹
为了在运行时连接到多个数据库,我创建了另一个构造函数,将连接字符串作为参数,如下所示,在同一文件Model.Context.cs
public WMSEntities(string connStringName)
: base("name=" + connStringName)
{
}
现在,我在Web中添加了其他连接字符串。配置例如
<add name="WMSEntities31" connectionString="data source=TESTDBSERVER_NAME;
initial catalog=TESTDB;userid=TestUser;password=TestUserPW/>
<add name="WMSEntities" connectionString="data source=TESTDBSERVER_NAME12;
initial catalog=TESTDB12;userid=TestUser12;password=TestUserPW12/>
然后,当连接到数据库时,我调用下面的方法传递connetionString
名称作为参数
public static List<v_POVendor> GetPOVendorList(string connectionStringName)
{
using (WMSEntities db = new WMSEntities(connectionStringName))
{
vendorList = db.v_POVendor.ToList();
}
}
我碰巧真的很喜欢EF Code First,但我不确定它适合你正在做的事情。你的模式多久改变一次?
你应该使用EF吗?
EF的优点
如果模式有规律地更改,EF Code First的迁移部分可能会为您节省大量的时间和精力,因为您经常可以不使用SQL脚本进行模式升级——模式更改最终会与其他代码一起出现在源存储库中。从这里开始:
https://stackoverflow.com/a/8909092/176877我也碰巧真的很喜欢EF的设置是多么容易,以及编写LINQ查询对它是多么容易,并返回我从DB构建的poco。
但是EF可能不是最合适的。
其他要考虑的orm
许多其他orm支持LINQ和POCOs,并更好地支持现有数据库(在EF Code First中有一些东西很难映射),以及现有的异步操作支持(EF现在是5.0;6.0有async)——(更新:EF6是最新的,它的异步支持很棒。它的批量删除是可怕的,应该避免像瘟疫一样,放弃普通的SQL)。
特别是NHibernate是现有数据库支持的野兽,但它的配置有点繁琐,而且似乎是政治上的内讧导致了不同版本和分支的文档冲突。
更简单的是许多&;Micro orms &;-这个链接是2011年的一个简短列表,但如果你四处看看,你会发现。net中有30个左右。有些会生成更好或更差的查询,有些根本没有,有些会让您编写SQL(不要使用这些)-您必须四处寻找以决定哪种适合您。这可能是一个更大的研究任务,但我认为其中一个简单的配置和小的学习曲线最适合你想做的。
回答你的具体问题
一次与所有客户端db对话
如果你同时从一个应用程序连接到所有50个数据库,你需要实例化50个DbContexts,如:
var dbClient1 = new DbClient1();
var dbClient2 = new DbClient2();
假设你做了一个小的包装类,如:
public class DbClient1 : CoreDbContext
{
public DbClient1()
: base("DbClient1") // Means use the connection string named "DbClient1" in Web.Config
CoreDbContext是项目中的主要EF类,它扩展了DbContext(任何EF项目的标准部分)。
一次只和一个人说话
如果你只使用一个应用程序,那么任何EF教程都可以。
唯一的主要技巧是在模式发生更改时迁移那些db。有两种基本方法。无论哪种方式,您都可以获取备份并在本地恢复它们的副本,以便您可以根据它们测试迁移(update-database -f -verbose
)。如果不这样做,就会冒着数据错误的风险,比如将列更改为NOT NULL,并发现本地测试实例没有空值,一个客户端的测试实例没有空值,就会崩溃。一旦你让它们正常工作,你就开始决定你想要如何更新生产。有很多方法可以做到这一点,包括使用签入git的SQL脚本编写自定义前滚/回滚工具(或找到一个),雇佣DBA,或者更简单:
The Obvious - SQL Script
转储迁移到SQL (update-database -script
),并在实际的生产数据库上运行它。
我的疯狂方式为少量的Dbs
为每个数据库添加条目到Web。配置,并为它们中的每一个创建一个项目配置,如"DbDeployClient1,"DbDeployClient2,"等。在每一个中创建一个类似DbDeployClient1的构建定义,然后将其添加到DbContext类中:
public CoreDbContext()
#if DbDeployClient1
: base("DbDeployClient1")
#elseif DbDeployClient2
: base("DbDeployClient2")
// etc
#endif
{
允许您快速切换到DbDeploy配置,并直接从Visual Studio针对目标数据库运行迁移。显然,如果你这样做,你需要临时打开一个端口,最好只允许你的IP,在实际的SQL Server实例上你正在迁移。其中一个优点是,您可以立即从迁移中获得明确的错误,以及完整的回滚功能,而无需任何实际工作—您所利用的所有回滚支持都只是EF的一部分。一个开发人员可以在没有其他瓶颈的情况下做到这一点。但是它有很多机会来降低风险和提高自动化程度。