Невозможно использовать существующую базу данных в модульных тестах с картой Effort

Я пытаюсь написать тест с использованием базы данных, размещенной в Azure SQL, с Effort framework на Entity Framework 6.

При выполнении следующего кода генерируется исключение:

[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: необработанное исключение при попытке инициализировать содержимое таблицы "Таблица" --- > System.ArgumentException: ключевое слово не поддерживается: "источник данных".

Такое же исключение возникает при замене EffortProviderConfiguration.RegisterProvider() на параметры app.config.

При использовании точно такой же строки соединения для создания UsersDbContext она преуспевает, и данные доступны. Кроме того, создание контекста с постоянным или временным режимом Effort, без строки подключения, тоже хорошо работает.

Что нужно сделать, чтобы инициализировать соединение с существующими данными из реальной БД?

Ответ 1

Вы указываете строку подключения в неправильном формате. Вы используете формат строки соединения ADO.NET/Linq2SQL, когда EntityDataLoader требует строку подключения, которая будет соответствовать EntityConnection (класс из 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' "

Прямо сейчас в вашем коде вы указываете только часть Connection Connection String.

Ответ 2

Если вы похожи на меня, вы сбиты с толку, почему вы должны дать Effort строку соединения вообще (так как она работает с базой данных в памяти и вы напрямую указываете свой контекст), документация делает его более понятным - это требуется только в том случае, если вы используете базовые или первые версии модели Entity Framework, потому что строка соединения Entity предоставляет информацию, необходимую для поиска вашей модели, чтобы она могла построить схему из нее! Таким образом, вы можете безопасно заполнять части идентификатора/пароля сервера/базы данных/пользователя строки подключения с именами фиктивных имен.

Это также дает понять, что настраиваемый по умолчанию подход DbConnectionFactory работает только для кода, что объясняет первые несколько часов ошибок, которые я получал... Сначала для первой модели или базы данных вам необходимо ввести Entity Connection в ваш класс сущности, как описано здесь.

Полезный совет - поскольку класс сгенерированной сущности-модели является частичным классом, вы можете создать другой файл кода в той же сборке, предоставить ему одно и то же пространство имен и сделать его также частичным классом, и вы можете добавить второй конструктор, необходимый для установки EntityConnection в этот файл кода, таким образом, когда вы изменяете/воссоздаете модель сущности, код с настраиваемым конструктором не будет удаляться с помощью шаблона t4.

Ответ 3

Я считаю, что ваша строка подключения должна быть представлена ​​как строка подключения стиля 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);
}