Entity Framework 7内存数据库异常

3

在使用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()会抛出一个异常。

“System.ArgumentException”类型的异常发生在“EntityFramework.Core.dll”中,但未在用户代码中处理。

附加信息:具有相同键但不同值的元素已经存在。 键:Microsoft.Data.Entity.ChangeTracking.Internal.SimpleKeyValue`1[System.Int32]。

我知道发生了什么,但我不知道为什么。
当第二次调用MembershipContext context = new MembershipContext(optionsBuilder.Options);时,将会创建上下文,但是context.Members已经包含了第一次创建上下文时的条目,因此会引发异常。

似乎指向第一次创建的相同实例。 - Preet Singh
我的猜测是有一些静态构造函数。当更改上下文所指向的数据库时,我曾在EF 5中看到类似的情况--http://nodogmablog.bryanhogan.net/2013/08/entity-framework-in-an-dynamics-nav-navision-environment/。 - Bryan
1个回答

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; }
    }
}

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