EF6 - 更正SQL输出但数据不会填充

时间:2017-12-05 21:32:48

标签: c# entity-framework linq many-to-many

我试图使用多对多关系填充引用表实体的子实体。

我有3个表:地址,成员和成员地址。地址和成员各有一个MemberAddresses集合。 MemberAddresses具有一个带有复合键的Address和Member对象。以下是相关映射:

地址

HasMany(x => x.MemberAddresses).WithRequired(x => x.Address).HasForeignKey(x => x.AddressId);

成员

HasMany(x => x.MemberAddresses).WithRequired(x => x.Member).HasForeignKey(x => x.MemberId);

MemberAddresses

HasRequired(rp => rp.Member).WithMany(x => x.MemberAddresses).HasForeignKey(rp => rp.MemberId);

当我着手执行以下操作时,我没有将任何子对象加载到Local扩展中(即Address和Member都为null):

_context.MemberAddresses.Include(rp => rp.Address).Where(rp => rp.MemberId == member.MemberId).Load();

有趣的是,EF的输出SQL正在执行正确的提取(我对SQL Server进行了检查)。如果我尝试使用带有ToList()的linq查询,它将按预期工作。它似乎是特定加载不起作用,并且不会填充子对象。

修改 为了更加清晰,我尝试使用简单的linq查询语法来实现相同的结果:

            var results = (from ma in _context.MemberAddresses
                       where ma.MemberId == parentMember.MemberId
                       select ma).Include(x => x.Address).Include(x => x.Member).ToList();

这可以使用完全填充的MemberAddresses列表填充结果。但是,它没有被添加到_context.MemberAddresses.Local实例中。

更奇怪的是,如果我首先使用linq查询,然后执行上面的加载线,结果现在从内存中删除子对象。也就是说,它仍然具有两个子表的ID,但丢失了子对象实例。

1 个答案:

答案 0 :(得分:0)

我无法重复使用Load()和枚举结果的任何差异。

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;

namespace Ef6Test
{

    public class Address
    {
        public int Id { get; set; }
        public virtual ICollection<MemberAddress> MemberAddresses { get; } = new HashSet<MemberAddress>();
    }
    public class Member
    {
        public int Id { get; set; }
        public virtual ICollection<MemberAddress> MemberAddresses { get; } = new HashSet<MemberAddress>();
    }
    public class MemberAddress

    {
        public Address Address { get; set; }
        [Key( ), Column(Order =0)]
        public int AddressId { get; set; }
        public Member  Member{ get; set; }

        [Key(), Column(Order = 1)]
        public int MemberId{ get; set; }

    }
    class Db : DbContext
    {
        public DbSet<Address> Address { get; set; }
        public DbSet<Member> Member{ get; set; }
        public DbSet<MemberAddress> MemberAddresses { get; set; }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

        }
    }




    class Program
    {
        static void Main(string[] args)
        {

            Database.SetInitializer(new DropCreateDatabaseAlways<Db>());

            using (var db = new Db())
            {
                db.Database.Initialize(true);


                var m = new Member();

                for (int i = 0; i < 10; i++)
                {
                    var a = new Address();
                    var ma = new MemberAddress();
                    ma.Address = a;
                    ma.Member = m;
                    db.Address.Add(a);
                    db.MemberAddresses.Add(ma);
                }


                db.Member.Add(m);
                db.SaveChanges();

            }

            Console.WriteLine("Enumerating Include Query");
            using (var db = new Db())
            {

                db.Database.Log = m => Console.WriteLine(m);

                var list = db.MemberAddresses.Include(rp => rp.Address).Where(rp => rp.MemberId < 10).ToList();

                foreach (var e in db.ChangeTracker.Entries())
                {
                    Console.WriteLine(e.Entity.GetType().Name);
                }
                var a = db.ChangeTracker.Entries<MemberAddress>().First();
                Console.WriteLine($"Address IsLoaded: {a.Reference<Address>("Address").IsLoaded}");

                Console.WriteLine($"Member Local {db.Member.Local.Count} items");
                foreach (var member in db.Member.Local)
                {
                    Console.WriteLine($"Member {member.Id}");
                }
                Console.WriteLine($"MemberAddress Local {db.MemberAddresses.Local.Count} items");
                foreach (var ma in db.MemberAddresses.Local)
                {
                    Console.WriteLine($"MemberAddress {ma.MemberId},{ma.AddressId}");
                }
                Console.WriteLine($"Address Local {db.Address.Local.Count} items");
                foreach (var ad in db.Address.Local)
                {
                    Console.WriteLine($"Address {ad.Id}");
                }


            }

            Console.WriteLine("Using Load()");
            using (var db = new Db())
            {

                db.Database.Log = m => Console.WriteLine(m);

                db.MemberAddresses.Include(rp => rp.Address).Where(rp => rp.MemberId < 10).Load();

                foreach (var e in db.ChangeTracker.Entries())
                {
                    Console.WriteLine(e.Entity.GetType().Name);
                }
                var a = db.ChangeTracker.Entries<MemberAddress>().First();
                Console.WriteLine($"Address IsLoaded: {a.Reference<Address>("Address").IsLoaded}");

                Console.WriteLine($"Member Local {db.Member.Local.Count} items");
                foreach (var member in db.Member.Local)
                {
                    Console.WriteLine($"Member {member.Id}");
                }
                Console.WriteLine($"MemberAddress Local {db.MemberAddresses.Local.Count} items");
                foreach (var ma in db.MemberAddresses.Local)
                {
                    Console.WriteLine($"MemberAddress {ma.MemberId},{ma.AddressId}");
                }
                Console.WriteLine($"Address Local {db.Address.Local.Count} items");
                foreach (var ad in db.Address.Local)
                {
                    Console.WriteLine($"Address {ad.Id}");
                }

            }



            Console.WriteLine("Hit any key to exit");
            Console.ReadKey();
        }
    }
}

输出

Enumerating Include Query
Opened connection at 12/6/2017 8:33:59 AM -06:00

SELECT
    [Extent1].[AddressId] AS [AddressId],
    [Extent1].[MemberId] AS [MemberId]
    FROM [dbo].[MemberAddresses] AS [Extent1]
    WHERE [Extent1].[MemberId] < 10


-- Executing at 12/6/2017 8:34:00 AM -06:00

-- Completed in 15 ms with result: SqlDataReader



Closed connection at 12/6/2017 8:34:00 AM -06:00

MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
Address IsLoaded: True
Member Local 0 items
MemberAddress Local 10 items
MemberAddress 1,1
MemberAddress 1,2
MemberAddress 1,3
MemberAddress 1,4
MemberAddress 1,5
MemberAddress 1,6
MemberAddress 1,7
MemberAddress 1,8
MemberAddress 1,9
MemberAddress 1,10
Address Local 10 items
Address 1
Address 2
Address 3
Address 4
Address 5
Address 6
Address 7
Address 8
Address 9
Address 10
Using Load()
Opened connection at 12/6/2017 8:34:00 AM -06:00

SELECT
    [Extent1].[AddressId] AS [AddressId],
    [Extent1].[MemberId] AS [MemberId]
    FROM [dbo].[MemberAddresses] AS [Extent1]
    WHERE [Extent1].[MemberId] < 10


-- Executing at 12/6/2017 8:34:00 AM -06:00

-- Completed in 8 ms with result: SqlDataReader



Closed connection at 12/6/2017 8:34:00 AM -06:00

MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
MemberAddress
Address_B9AEC76E2DAA985CBBFB722E4D5F60354D0FC4633617474BEE39DD928330C226
Address IsLoaded: True
Member Local 0 items
MemberAddress Local 10 items
MemberAddress 1,1
MemberAddress 1,2
MemberAddress 1,3
MemberAddress 1,4
MemberAddress 1,5
MemberAddress 1,6
MemberAddress 1,7
MemberAddress 1,8
MemberAddress 1,9
MemberAddress 1,10
Address Local 10 items
Address 1
Address 2
Address 3
Address 4
Address 5
Address 6
Address 7
Address 8
Address 9
Address 10
Hit any key to exit