我有多个具有相同架构的数据库。 在我的代码中,我想通过参数查询其中一个DB,该参数会动态更改。
现在它看起来像这样:
public void saveNewUser(User user, string type)
{
if (type == "A")
{
using (var db = new AEntities())
{
db.Users.Add(user);
db.SaveChanges();
}
}
else
{
using (var db = new BEntities())
{
db.Users.Add(user);
db.SaveChanges();
}
}
}
相反,我想做这样的事情:
public void saveNewUser(User user, string type)
{
using (var db = new GeneralEntity(type))
{
db.Users.Add(user);
db.SaveChanges();
}
}
有什么好主意吗?
答案 0 :(得分:1)
根据我的经验,我只有一个DbContext来解决类似的问题。我只是在运行时修改连接字符串。实体框架通过允许您使用连接字符串调用构造函数来支持此功能。
我允许管理员将设置作为配置文件进行维护,对于给定的模型,应用程序将其存储为加密SQL设置的集合。在运行时,此列表作为字典加载,其中配置文件名称(“A”,“B”)用作键。
然后使用需要连接字符串的DbContext构造函数,并根据目标db传递一个构建的连接字符串:
// the model name in the app.config connection string (any model name - Model1?)
private string BuildConnectionString(string profile)
{
// configuration would hold the collection of settings - however you prefer to provide this
var settings = configuration.GetConnectionSettings(profile);
// Build the provider connection string with configurable settings
var providerSB = new SqlConnectionStringBuilder
{
InitialCatalog = settings.InitialCatalog,
DataSource = settings.DataSource,
UserID = settings.User,
Password = settings.Password
};
var efConnection = new EntityConnectionStringBuilder();
// or the config file based connection without provider connection string
// var efConnection = new EntityConnectionStringBuilder(@"metadata=res://*/model1.csdl|res://*/model1.ssdl|res://*/model1.msl;provider=System.Data.SqlClient;");
efConnection.Provider = "System.Data.SqlClient";
efConnection.ProviderConnectionString = providerSB.ConnectionString;
// based on whether you choose to supply the app.config connection string to the constructor
efConnection.Metadata = "res://*/Model.DbEntities.csdl|res://*/Model.DbEntities.ssdl|res://*/Model.DbEntities.msl", model;
return efConnection.ToString();
}
然后在您的示例中,您将只使用一个DbContext:
using (var db = new DbEntities(BuildConnectionString("A")))
{
db.Users.Add(user);
db.SaveChanges();
}
答案 1 :(得分:0)
可能会使用类似工厂类的东西吗?
public void saveNewUser(User user, string type)
{
using (var db = myclass.GetGeneralEntity(type))
{
db.Users.Add(user);
db.SaveChanges();
}
}
答案 2 :(得分:0)
DbContext方法Set<TEntity>返回通用DbSet<TEntity>。您可以使用此而不是添加的属性来覆盖DbContext
,即。在您的调用代码中引用基类DbContext
,它不关心DbContext
的实际实例是什么。
public class MyClass {
private DbContext _context;
public MyClass(DbContext context){
_context = context;
}
public void saveNewUser(User user)
{
_context.Set<User>.Add(user);
_context.SaveChanges();
}
}
上面的示例依赖于DI在构造函数中获取正确的DbContext
实例,只要它稍后知道实体User
时就不关心哪个具体实现调用方法saveNewUser
(否则将抛出异常)。 DI框架还可以处理处理创建的DbContext
,或者您可以实现IDisposable
到MyClass
并在处置方法中处置DbContext
。或者,您可以注入DbContext
工厂以在需要时创建一个工厂。 (有很多选项,只取决于您的首选框架,可能还有您的应用目前的结构)。
我认为你的意思是实际的底层实体是完全相同的类型。如果这是错误的并且还有许多User
类型,那么这将无效。
答案 3 :(得分:0)
我在寻找的是如何动态返回AEntity / BEntity,对象已经存在。
我所做的是:
protected override void OnStart()
{
if (WCHSBMobileApplication.Current.SuperBillObject == null)
{
AddSuperBill();
}
else
{
EditSuperBill();
}
}
为了动态接收类型:
public class DbContextGeneral : DbContext
{
public virtual Users;
}
public class AEntity : DbContextGeneral
{
public override Users;
}
public class BEntity : DbContextGeneral
{
public override Users;
}
然后,最后:
private DbContextGeneral GetDBInstance(string value)
{
if (value == "A")
{
return new AEntity();
}
return new BEntity();
}