动态切换数据库(EF框架)
文章简略:本文测试项目为Silverlight+EF+RIA Service动态切换数据库的问题
通常,Ado.net EntityFramework的数据库连接字符串ConnectionString是存在实体框架所在的类库项目中的配置文件中(.config)的,类似这样:
<connectionStrings>
<add name="{EFName}Entities" connectionString="metadata=res://*/Model1.csdl|
res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;
provider connection string="data source={IP};
initial catalog=Northwind;persist security info=True;user id=sa;
password={PWD};multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
EntityConnection的ConnectionString和以前的Ado.net的ConnectionString是有一些的区别的。有2个新元素,解释下:
metatata: 指定Entity Framework数据模型的路径,包括CSDL(概念架构定义语言)、SSDL(存储架构定义语言)、MSL(映射规范语言)的路径
provider: 数据库provider,例如SQLServer的默认Ado.net:System.Data.SqlClient,也可以是其它的数据库例如Oracle、SQLite、MySql等
需要注意的是:EF框架默认寻找的数据库连接数据库字符串不一定是当期类库或者项目,严谨的说法是,解决方案下的启动项目所在的配置文件中寻找连接
这是用配置的方式指定ConnectionString,也可以用代码动态指定Entity framework的数据库连接,用SqlConnectionStringBuilder手动创建:
public partial class EFNameEntities
{
partial void OnContextCreated()
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder
((EntityConnection)Connection).StoreConnection.ConnectionString);
builder.IntegratedSecurity = false;
builder.UserID = "sa";
builder.Password = "";
builder.InitialCatalog = "";
((EntityConnection)Connection).StoreConnection.ConnectionString = builder.ConnectionString;
}
}
这样ConnectionString就写死了,不能满足实际的开发需求,所以还是要用Web.config配置的方式。
下面我们做一个测试,我们在Web.config添加一个数据库连接方式用来测试,关键词叫“MyTestDBConn”
<connectionStrings>
<add name="EFNameEntities" connectionString="metadata=res://*/Model1.csdl|res:
//*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;
provider connection string="data source=192.168.1.88;
initial catalog=Northwind;persist security info=True;user id=sa;password={};
multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
<add name="MyTestDBConn" connectionString="metadata=res://*/Model1.csdl|res:
//*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;
provider connection string="data source=192.168.1.100;
initial catalog=Northwind_AAA;persist security info=True;
user id=sa;password={PWD};multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
在Domain Service中改变EntityFramework的ConnectionString,这儿指定用"MyTestDBConn":
using System.Configuration; [EnableClientAccess()]
public class TestDomainService : LinqToEntitiesDomainService<TestEntities>
{
protected override TestEntities CreateObjectContext()
{
string connection = ConfigurationManager.ConnectionStrings["MyTestDBConn"].ConnectionString;
return new TestEntities(connection);
}
}
这样的确可以在DomainService切换Entity Framework数据库连接ConnectionString,但我如果有好多DomainService怎么办,岂不是每一个都要这样来一下子?第二 个问题是,如何把"MyTestDBConn"作为一个参数传进来?
先解决第一个问题,我们写一个DomainService的基类,继承原来的基类:LinqToEntitiesDomainService,然后让每一个DomainService继承这个新的基类即可
using System;
using System.Data.Objects;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Server;
using System.Configuration; public abstract class DomainServiceBase<TContext> : LinqToEntitiesDomainService<TContext>
where TContext : ObjectContext, new()
{
protected override TContext CreateObjectContext()
{
string connection = ConfigurationManager.ConnectionStrings["MyTestDBConn"].ConnectionString; Type contextType = typeof(TContext);
object objContext = Activator.CreateInstance(contextType, connection); return objContext as TContext;
} protected override void OnError(DomainServiceErrorInfo errorInfo)
{
// Deal with errors
}
}
//接着,让你的DomainService继承这个基类,不要继承LinqToEntitiesDomainService了
EnableClientAccess()]
public class TestDomainService : DomainServiceBase<TestEntities>
{
//...
}
第二个问题是如何把"MyTestDBConn"这个ConnectionString关键词作为参数传进来?这个问题有点难。上面说的都是在 服务器端指定连接到哪个数据库服务器,如何实现在客户端用户登录的时候,有个下拉框选择数据库服务器,然后在Silverlight客户端把这个参数传递 到服务器端DomainService并连接到指定的数据库服务器?
如果用上面的思路,就是要在DomainService的构造函数上动手,加一个参数string databaseKey,但是这个有点罗嗦。为什么?因为DomainService不是一般的class,它是WCF Service,在DomainService里面的每一个方法就是一个定义了request和response的contract的WCF (Web Service),只不过WCF Ria Services隐藏了这些调用WCF的复杂性,让你感觉在客户端就可以简单的调用DomainService。所以,如果你要给 DomainService的构造函数传一个参数,就要研究一下如何给WCF Service的构造函数传递一个参数的方法,可以用IInstanceProvider和ServiceBehavior来实现,代码见这篇文章。
这里我用另外一个Session的方法来实现更简单,每个客户端session不同,所以在客户端用户登录的时候,有个下拉框选择数据库服务 器,然后在Silverlight客户端把这个参数传递到服务器端DomainService并让Entity framework连接到指定的数据库服务器是可以用Session来实现的。具体方法是在DomainService里加一个SetDatabase函 数设置数据库,客户端把参数传给服务端,并保存到Session。然后重载CreateObjectContext ()函数并根据Session的值连接到指定的数据库。最后在SetDatabase这个函数的Callback时读取真正的数据。代码:
在DomainService里面加个SetDatabase()方法:
using System.Web; [EnableClientAccess()]
public class TestDomainService : LinqToEntitiesDomainService<TestEntities>
{
public void SetDatabase(string Database)
{
HttpContext.Current.Session["UserDatabase"] = Database;
}
} 在DomainService里面重载CreateObjectContext()方法:
using System.Web; [EnableClientAccess()]
public class TestDomainService : LinqToEntitiesDomainService<TestEntities>
{
protected override TestEntities CreateObjectContext()
{
if (HttpContext.Current.Session["UserDatabase"] != null)
{
string connection = ConfigurationManager.ConnectionStrings[HttpContext.Current.Session["UserDatabase"].ToString()].ConnectionString;
return new TestEntities(connection);
}
else
return base.CreateObjectContext();
}
} 前台调用xaml.cs:
public partial class MainPage : UserControl
{
private DomainService1 s = new DomainService1(); public MainPage()
{
InitializeComponent(); //使用MyTestDBConn作为ConnectionString,加载数据到DataGrid
LoadData("MyTestDBConn");
} private void button1_Click(object sender, RoutedEventArgs e)
{
//使用Web.config中另外一个ConnectionString,加载数据到DataGrid
LoadData("YourEntities");
} //EF连接指定的ConnectionString
//Param: database - web.config中ConnectionString的Name关键词
private void LoadData(string database)
{
this.busyIndicator1.IsBusy = true;
//****SetDatabase callback的时候读取数据*********
s.SetDatabase(database, (InvokeOperation) =>
{
//GetCompanies改为你自己的方法
s.Load(s.GetCompaniesQuery(), (t) =>
{
dataGrid1.ItemsSource = t.Entities;
this.busyIndicator1.IsBusy = false;
}, true);
}, null);
}
}
可以另外按照上面DomainServiceBase的方法写一个基类避免每个DomainService重写一遍。
结束
不知道大家有没有更好的方法实现客户端传参到服务端动态切换数据库呢?另:由于Entity framework的模型是由链接到本地数据库映射生成的,所以不提供源码下载了,按照本文的步骤一步步做就能运行。如果对 Silverlight+Wcf Ria service+EF还不明白的,可以看博客园其他的博文。
参考文章:http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/8f18aed8-8e34-48ea-b8be-6c29ac3b4f41
动态切换数据库(EF框架)的更多相关文章
- 【TP3.2】 动态切换数据库方法
1 config 配置: 'connection' => 'mysql://root:root@localhost:3306/dbname', connection 数据库连接字符串,后面代码 ...
- 封装了一些sqlsugar的常用方法 用来动态切换数据库和依赖注入 支持泛型
接口: /// <summary> /// 数据库操作 /// </summary> public interface IDAL_Services { /// <summ ...
- jdbc动态切换数据库
http://www.oschina.net/code/snippet_140474_50797
- Spring AOP动态切换数据源
现在稍微复杂一点的项目,一个数据库也可能搞不定,可能还涉及分布式事务什么的,不过由于现在我只是做一个接口集成的项目,所以分布式就先不用了,用Spring AOP来达到切换数据源,查询不同的数据库就可以 ...
- EntityFramework For Mysql 动态切换数据源
1.简介 在工作中遇到一个问题.项目有三个数据库(三个数据库表结构一样),用户可以选择使用哪个数据库.其实就是动态切换数据库连接. 2.EntityFramework For Mysql 先来简单的介 ...
- Spring动态切换多数据源事务开启后,动态数据源切换失效解决方案
关于某操作中开启事务后,动态切换数据源机制失效的问题,暂时想到一个取巧的方法,在Spring声明式事务配置中,可对不改变数据库数据的方法采用不支持事务的配置,如下: 对单纯查询数据的操作设置为不支持事 ...
- Pytest测试框架一键动态切换环境思路及方案
前言 在上一篇文章<Pytest fixture及conftest详解>中,我们介绍了fixture的一些关键特性.用法.作用域.参数等,本篇文章将结合fixture及conftest实现 ...
- C# CodeFirst(EF框架)代码优先创建数据库
namespace WebEF.Model{ public class ModelContext:DbContext //继承DBcontext 来自EF框架 { public ModelContex ...
- Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)
一.缘由 上一篇文章Spring3.3 整合 Hibernate3.MyBatis3.2 配置多数据源/动态切换数据源 方法介绍到了怎么样在Sping.MyBatis.Hibernate整合的应用中动 ...
随机推荐
- 第一周python入门
第一编程语言的分类: 1.机器语言 二进制编程 直接操作硬件 优点:执行速度快 缺点:开发效率低 面向机器编程 2.汇编语言 英文标签代替一串特定的二进制,直接操作硬件 缺点开发效率低 面向 ...
- R语言中将hello打印10次的两种方法
我们有两种方法来做这件事情: 1.for结构 for循环重复的执行一个语句,直到某个变量的值不再包含在序列seq中为止. 语法: for (var in seq) statement 例如: > ...
- Openstack(Kilo)安装系列之glance(六)
安装配置 Before you install and configure the Image service, you must create a database, service credent ...
- Canvas清屏的实现
/** * Canvas清屏的操作 * * 參考资料: http://blog.csdn.net/lfdfhl/article/details/9076001 * */ private void cl ...
- Django实现组合搜索的方法示例
目录 一.实现方法 二.基本原理 三.代码样例 方法1:纯模板语言实现 方法二:使用simpletag实现 四.其他变化 1.model定义 2.处理函数变化 3.simpletag相应改变 一. ...
- [MySQL] 变量(参数)的查看和设置 [转]
[MySQL] 变量(参数)的查看和设置 类似于Oracle的参数文件,MySQL的选项文件(如my.cnf)用于配置MySQL服务器,但和Oracle叫法不一样,在MySQL里, 官方叫变量(Var ...
- python中的str()与eval函数
author:headsen chen date:2018-04-09 10:48:22 eval函数是把str转化成list.dict.tuple str函数把list,dict,tuple ...
- Asp.Net WebApi核心对象解析
在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...
- float元素一定要闭合
float:left; float:right; 一定要两个元素一起放float
- mysqldump迁移说明
使用mysqldump导出数据, 数据包含单行insert,带字段值 #使用mysqldump备份数据到文件, 主要在每个分片的主上面进行备份,确保数据是最新的. mysqldump -h192. - ...