使用Effort框架在单元测试中无法使用现有数据库

13
我会尝试使用Effort框架在Entity Framework 6上,使用托管在Azure SQL中的数据库编写测试。
执行以下代码时,会抛出异常:
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
    EffortProviderConfiguration.RegisterProvider();
}

[TestMethod]
public void TestMethod1()
{
    const string connectionString = "Data Source=***;Initial Catalog=my_catalog;User ID=user;Password=password;provider=System.Data.SqlClient";
    IDataLoader loader = new EntityDataLoader(connectionString);
    using (var ctx = new UsersDbContext(Effort.DbConnectionFactory.CreatePersistent("cool", loader)))
    {
        var usersCount = ctx.Users.Count();
    }
}

Count()执行时抛出异常:

Effort.Exceptions.EffortException: 尝试初始化'Table'表内容时发生未处理的异常 ---> System.ArgumentException: 关键字不受支持:'data source'。

使用app.config设置替换EffortProviderConfiguration.RegisterProvider()时,也会抛出相同的异常。

当使用完全相同的连接字符串创建UsersDbContext时,它可以成功并且数据是可访问的。此外,使用Effort持久或瞬态模式创建上下文,而无需连接字符串,也能正常工作。

应该如何初始化与现有数据源的连接?


嗯,如果您使用“Server”而不是“Data Source”会发生什么?就SQL Server而言,这是一个同义词,但也许Effort不知道... - Pragmateek
只是出于兴趣,如果从连接字符串中删除“数据源”,会发生什么? - wal
1
嗨,以上的方法都没有帮助。当我将“数据源”键更改为“服务器”时,它会抱怨只有现在的“服务器”键不支持关键字。如果我从连接字符串中删除数据源,它会继续抱怨连接字符串中的下一个键“初始目录”不受支持。 - Lena Kaplan
3个回答

6
如果你和我一样困惑为什么你需要给Effort提供一个连接字符串(因为它使用内存数据库,而你直接为上下文提供了连接),那么文档可以让你更清楚 - 仅当你使用数据库优先或模型优先的Entity Framework变体时才需要它, 因为实体连接字符串提供了Effort定位模型所需的信息,以便它可以从中构建模式!因此,你可以安全地使用虚拟名称填充连接字符串的服务器/数据库/用户ID/密码部分。
这也说明自定义默认DbConnectionFactory方法仅适用于Code First,这解释了我遇到的前几个小时的错误...对于模型优先或数据库优先,你必须将实体连接注入到你的实体类中,如这里所述。
一个有用的提示 - 因为生成的实体模型类是一个部分类,所以你可以在同一个程序集中创建另一个代码文件,给它相同的命名空间,并将其作为部分类,然后将第二个构造函数添加到该代码文件中,以设置EntityConnection,这样当你修改/重新创建实体模型时,具有自定义构造函数的代码不会被t4模板删除。

请参考此答案,该答案更详细地解释了Effort仅从连接字符串中提取元数据部分以便创建模式。 - John Cummings

3
您正在使用ADO.NET/Linq2SQL连接字符串格式,而实体数据加载程序需要适合EntityFramework的连接字符串。您指定的连接字符串格式错误。您可以在此处了解有关EF的连接字符串:http://msdn.microsoft.com/en-us/library/system.data.entityclient.entityconnection.connectionstring(v=vs.110).aspx。简而言之,您的连接字符串应该如下所示:
"Provider=System.Data.SqlClient; 
 Metadata=c:\metadata|c:\Metadata\Sql; 
 Provider Connection String='Data Source=localhost; Initial Catalog=AdventureWorks;Integrated Security=True;Connection Timeout=60' "

目前在你的代码中,你只指定了提供程序连接字符串部分。


1

我相信你的连接字符串必须以EF风格的连接字符串提供。例如在你的app.config或者webconfig中:

<add name="dbConnectionString" connectionString="metadata=res://*/Models.YourEntityModel.csdl|res://*/Models.YourEntityModel.ssdl|res://*/Models.YourEntityModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=yourdatasource;initial catalog=yourdb;persist security info=True;user id=username;password=password;multipleactiveresultsets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

[TestMethod]
public void MyTestMethod()
{
    //Arrange
    //Then you can specify your connection string with its name:
    EntityConnection connection =
    Effort.EntityConnectionFactory.CreateTransient("name=dbConnectionString");

    //Act
    var usersCount;
    using (MyDbContext ctx= new MyDbContext(connection))
    {
        usersCount = ctx.Users.Count();
    }
    //Assert
    //Put your assert logic here:
    Assert.IsTrue(usersCount == 100);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接