2016-01-20 2 views
3

Я столкнулся с проблемой при использовании базы данных памяти для модульного тестирования с помощью EF 7. Следующее приложение продемонстрирует проблему.Entity Framework 7 в исключении базы данных базы данных

using System; 
using Microsoft.Data.Entity; 
using Microsoft.Data.Entity.Infrastructure; 

namespace EF7InMemoryBug 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      Program p = new Program(); 

      MembershipContext m1 = p.GetNewContext(); 
      MembershipContext m2 = p.GetNewContext(); 

      foreach (var member in m1.Members) 
      { 
       Console.WriteLine(member); 
      } 
     } 

     private MembershipContext GetNewContext() 
     { 
      var optionsBuilder = 
       new DbContextOptionsBuilder<MembershipContext>(); 
      optionsBuilder.UseInMemoryDatabase(); 

      MembershipContext context = new MembershipContext(optionsBuilder.Options); 

      Member member1 = new Member() 
      { 
       MemberId = 1, 
       FirstName = "James", 
       LastName = "Jones" 
      }; 

      context.Members.Add(member1); 
      context.SaveChanges(); 
      return context; 
     } 

    } 

    public class Member 
    { 
     public int MemberId { get; set; } 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 

     public override string ToString() 
     { 
      return $"{MemberId} {FirstName} {LastName}"; 
     } 
    } 

    public class MembershipContext : DbContext 
    { 
     public MembershipContext(DbContextOptions options) 
     : base(options) {} 
     public DbSet<Member> Members { get; set; } 
    } 
} 

После вызова MembershipContext m2 = p.GetNewContext(); исключение выбрасывается на context.SaveChanges().

Исключение типа «System.ArgumentException» произошло в EntityFramework.Core.dll, но не был обработан в пользовательском коде

Дополнительная информация: элемент с тем же ключом, но с другим значением уже существует. Ключ: Microsoft.Data.Entity.ChangeTracking.Internal.SimpleKeyValue`1 [System.Int32]

Я знаю, что происходит, но я не знаю, почему.

Когда MembershipContext context = new MembershipContext(optionsBuilder.Options); вызывается во второй раз, контекст создается, НО context.Members уже имеет запись с первого раза, когда я создал контекст, и, следовательно, исключение.

+0

похоже, что он указывает на тот же экземпляр, который был создан в первый раз –

+0

. У меня есть некоторый статический конструктор. Я видел что-то похожее на это с EF 5 при изменении базы данных, на которую указывает контекст: http://nodogmablog.bryanhogan.net/2013/08/entity-framework-in-an-dynamics-nav-navision- Окружающая среда/ – Bryan

ответ

1

Это не ошибка, это особенность. https://github.com/aspnet/EntityFramework.Docs/issues/95

Предлагаемый способ использования DI.

using System; 
using Microsoft.Data.Entity; 
using Microsoft.Data.Entity.Infrastructure; 
using Microsoft.Extensions.DependencyInjection; 

namespace EF7InMemoryBug 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      Program p = new Program(); 
      MembershipContext m1 = p.GetNewContext(); 
      MembershipContext m2 = p.GetNewContext(); 

      foreach (var member in m1.Members) 
      { 
       Console.WriteLine(member); 
      } 

      foreach (var member in m2.Members) 
      { 
       Console.WriteLine(member); 
      } 
     } 

     private MembershipContext GetNewContext() 
     { 
      var serviceCollection = new ServiceCollection(); 
      serviceCollection 
       .AddEntityFramework() 
       .AddInMemoryDatabase() 
       .AddDbContext<MembershipContext>(c => c.UseInMemoryDatabase()); 

      MembershipContext context = serviceCollection.BuildServiceProvider().GetService<MembershipContext>(); 

      Member member1 = new Member() 
      { 
       MemberId = 1, 
       FirstName = "James", 
       LastName = "Jones" 
      }; 

      context.Members.Add(member1); 
      context.SaveChanges(); 
      return context; 
     } 

    } 

    public class Member 
    { 
     public int MemberId { get; set; } 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 

     public override string ToString() 
     { 
      return $"{MemberId} {FirstName} {LastName}"; 
     } 
    } 

    public class MembershipContext : DbContext 
    { 
     public MembershipContext(DbContextOptions options) 
     : base(options) {} 
     public DbSet<Member> Members { get; set; } 
    } 
} 
Смежные вопросы