我们正在尝试为EF项目使用存储库模式。允许用户选择三个独立(但结构相同)数据库中的一个来登录(有一个用于培训,一个用于测试,一个用于生产)。
我们目前正在使用EF 4实现,并通过ADO.Net EntityObject Generator生成了我们的T4。我们的存储库基类如下所示:
public class RepositoryBase<C> : IDisposable
where C : ObjectContext, new()
{
private C _DataContext;
public virtual C DataContext
{
get
{
if (_DataContext == null)
{
_DataContext = new C();
}
return _DataContext;
}
}
//other code cut for brevity...
}
我认为我们想要的是能够修改“_DataConext = new C();” line,以便它可以使用在运行时生成的连接字符串指向正确的数据库。不幸的是,像这样传递连接字符串:_DataConext = new C(connectionString);不允许并导致此消息:“参数无法传递给类型参数上使用的'新'。”
我可以在model.tt文件的代码后面看到有三个构造函数:默认的无参数构造函数,一个具有EntityConnection参数的构造函数,第三个具有连接字符串参数(我们想要使用的参数)
问题是我们该如何做到这一点?任何帮助表示赞赏!
答案 0 :(得分:1)
嗯,问题是在泛型类型上指定一个带参数的构造函数。这是不允许的。 第一种解决方案是使用反射。 如果您知道定义的构造函数是什么:
public virtual C DataContext
{
get
{
if (_DataContext == null)
{
_DataContext = (C)Activator.CreateInstance(typeof(C), new object[]{ connectionString });
}
return _DataContext;
}
}
更好的解决方案是将C的实例提供给您的存储库的构造。
希望有所帮助
答案 1 :(得分:0)
我是否可以加入这个线程,对创建一个新的ObjectContext泛型实例有好奇心? 当我在没有Activator的情况下使用CreateContext方法(下面)时,它会创建一个带有“default”连接字符串的新实例,无论我给它什么连接。 使用Activator,它能够正确查找和创建它,我迷路了......
在我的app.config中有两者,但它只使用在制作edmx时创建的那个。
/// <summary>
/// Base repository
/// </summary>
public RepositoryBase(Connection.ConnectionManagerBase connectionmanager)
{
this.pContext = this.CreateContext(connectionmanager, (x => new C()));
this.ContextObjectSet = this.pContext.CreateObjectSet<T>();
}
/// <summary>
/// Create context with connection string
/// </summary>
/// <param name="connectionmanager">Connection manager</param>
/// <param name="factory">Factory context</param>
/// <returns>Instance</returns>
private C CreateContext(Connection.ConnectionManagerBase connectionmanager, Func<string, C> factory)
{
// this create instance with correct connection
return (C)Activator.CreateInstance(typeof(C), new object[] { connectionmanager.ConnectionString });
// this use the "default" connection, no matter what is in connectionmanager.ConnectionString
return factory(connectionmanager.ConnectionString);
}