0

我们正在尝试为 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();” 行,以便它可以使用在运行时生成的连接字符串来指向正确的数据库。不幸的是,像这样传递连接字符串:_DataConext = new C(connectionString); 不允许并导致此消息:“不能将参数传递给类型参数上使用的‘新’。”

我可以在 model.tt 文件后面的代码中看到有三个构造函数:默认的无参数构造函数,一个具有 EntityConnection 参数的构造函数,以及第三个具有连接字符串参数的构造函数(我们要使用的那个)。

问题是我们如何去做这件事?任何帮助表示赞赏!

4

2 回答 2

1

好吧,问题是在泛型类型上指定带有参数的构造函数。这是不允许的。第一个解决方案是使用反射。如果您知道定义的构造函数是什么:

public virtual C DataContext
{
    get
    {
        if (_DataContext == null)
        {
            _DataContext = (C)Activator.CreateInstance(typeof(C), new object[]{ connectionString });
        }
        return _DataContext;
    }
}

更好的解决方案是将 C 的实例提供给您的存储库的构造函数。

希望能帮助到你

于 2012-06-07T14:01:11.323 回答
0

我可以带着对创建新的 ObjectContext 通用实例的好奇心加入这个线程吗?当我在没有 Activator 的情况下使用 CreateContext 方法(如下)时,它会创建一个带有“默认”连接字符串的新实例,无论我给它哪个连接。使用 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);
    }
于 2012-06-24T10:42:36.097 回答