使用内存数据库进行EF 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()
上会抛出异常。
类型&#39; System.ArgumentException&#39;的例外情况发生在EntityFramework.Core.dll中但未在用户代码中处理
附加信息:具有相同键但不同的元素 价值已经存在。键: Microsoft.Data.Entity.ChangeTracking.Internal.SimpleKeyValue`1 [System.Int32]
我知道发生了什么,但我不知道为什么。
第二次调用MembershipContext context = new MembershipContext(optionsBuilder.Options);
时,会创建上下文,但是context.Members
从第一次创建上下文时就已经有了条目,因此是异常。
答案 0 :(得分: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; }
}
}