Entity Framework 7 en la excepción de la base de datos de memoria

c# entity-framework-core

Pregunta

Encontré un problema al usar la base de datos en memoria para pruebas de unidad con EF 7. La siguiente aplicación demostrará el problema.

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

Después de llamar MembershipContext m2 = p.GetNewContext(); se lanza una excepción en el context.SaveChanges() .

Se produjo una excepción del tipo 'System.ArgumentException' en EntityFramework.Core.dll pero no se manejó en el código de usuario

Información adicional: Ya existe un elemento con la misma clave pero un valor diferente. Clave: Microsoft.Data.Entity.ChangeTracking.Internal.SimpleKeyValue`1 [System.Int32]

Sé lo que está pasando, pero no sé por qué.

Cuando MembershipContext context = new MembershipContext(optionsBuilder.Options); se llama la segunda vez, el contexto se crea, PERO el context.Members Los context.Members ya tienen la entrada desde la primera vez que creé el contexto, por lo tanto, la excepción.

Respuesta aceptada

No es un error, es una característica. https://github.com/aspnet/EntityFramework.Docs/issues/95

Aquí está la forma sugerida de usar 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; }
    }
}



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué