2016-01-20 70 views
3

我在使用內存數據庫進行EF 7單元測試時遇到了問題。以下應用程序將演示此問題。內存數據庫異常中的實體框架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; } 
    } 
}