EF查询不返回导航属性的外键值

时间:2013-03-21 01:55:27

标签: entity-framework entity-framework-5 code-first

我正在使用EF5 Code First,并且禁用了延迟加载。我有以下代码:

//Model
public class Task
{
    public Guid Id {get; set;}
    //other properties that are not relevant here
    public Guid CreatorId {get; set;}
    public User Creator {get; set;}
    public Guid? OwnerId {get; set;}
    public User Owner {get; set;}
}

//Model
public class User
{
    public Guid Id { get; set; }
    //other properties that are not relevant here
    public string UserName { get; set; }

    public IList<Task> TasksCreated { get; set; }
    public IList<Task> TasksOwned { get; set; }
}

//Configuration for Task
public class TaskConfiguration : EntityTypeConfiguration<Task>
{
    public TaskConfiguration()
    {           
        HasRequired(task => task.Creator)
            .WithMany(creator => creator.TasksCreated)
            .HasForeignKey(task => task.CreatorId)
            .WillCascadeOnDelete(false);

        HasOptional(task => task.Owner)
            .WithMany(owner => owner.TasksOwned)
            .HasForeignKey(task => task.OwnerId)
            .WillCascadeOnDelete(false);
    }
}

当我查询任务时,所有数据都按预期返回。当我使用以下查询查询用户时,Owner或Creator的Tasks属性为null。 null值被分配给与我查询的User不匹配的任何属性。因此,如果User2是User1的任务的所有者,则User2的ID将返回,但Owner属性将为null。这是查询:

var db = new MyContext();
var user = db.Users
             .Include("TasksCreated")
             .Include("TasksOwned")
             .SingleOrDefault(u => u.UserName.Equals("user1", StringComparison.OrdinalIgnoreCase));

我不确定是否还有其他步骤我缺少或者我没有正确配置任务 - 用户关系。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

我尝试你的代码然后运行。 唯一的区别是我添加的上下文的构造函数:

public class TestEFContext : DbContext {
    public IDbSet<User> us { get; set; }
    public IDbSet<Task> ts { get; set; }

    public TestEFContext(String cs)
        : base(cs) {
        Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
    }

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

        Configuration.LazyLoadingEnabled = false;

        modelBuilder.Configurations.Add(new TaskConfiguration());            
    }
}

从这里开始:

class Program {
    static void Main(String[] args) {
        String cs = @"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";
        using (TestEFContext c = new TestEFContext(cs)) {
            User u1 = new User {
                Id = Guid.NewGuid(),
                UserName = "u1"
            };
            User u2 = new User {
                Id = Guid.NewGuid(),
                UserName = "u2"
            };
            c.us.Add(u1);
            c.us.Add(u2);
            Task t = new Task {
                Id = Guid.NewGuid(),
                Creator = u1,
                Owner = u1
            };                
            c.ts.Add(t);
            t = new Task {
                Id = Guid.NewGuid(),
                Creator = u2,
                Owner = u1
            };
            c.ts.Add(t);
            c.SaveChanges();                
        }

        using (TestEFContext c = new TestEFContext(cs)) {
            var user = c.us
             .Include("TasksCreated")
             .Include("TasksOwned")
             .SingleOrDefault(u => u.UserName.Equals("u1", StringComparison.OrdinalIgnoreCase));
            foreach (Task t in user.TasksCreated) {
                Console.WriteLine(t.Id);
            }
            Console.WriteLine("-----");
            foreach (Task t in user.TasksOwned) {
                Console.WriteLine(t.Id);
            }
        }
    }
}

按预期显示:

a415c8c6-6b0a-4e1b-a42f-cd4230cf4d4a
-----
a415c8c6-6b0a-4e1b-a42f-cd4230cf4d4a
a2e9c527-d8cb-4db7-8879-7febb1c30a07
Appuyez sur une touche pour continuer...

EDITION ========== ==========

以下代码也会运行:

using System;
using System.Linq;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;

namespace testef {
    //Model
    public class Task {
        public Guid Id { get; set; }
        //other properties that are not relevant here
        public String ShortDescription { get; set; }
        public Guid CreatorId { get; set; }
        public User Creator { get; set; }
        public Guid? OwnerId { get; set; }
        public User Owner { get; set; }
    }

    //Model
    public class User {
        public Guid Id { get; set; }
        //other properties that are not relevant here
        public string UserName { get; set; }

        public IList<Task> TasksCreated { get; set; }
        public IList<Task> TasksOwned { get; set; }
    }

    //Configuration for Task
    public class TaskConfiguration : EntityTypeConfiguration<Task> {
        public TaskConfiguration() {
            HasRequired(task => task.Creator)
                .WithMany(creator => creator.TasksCreated)
                .HasForeignKey(task => task.CreatorId)
                .WillCascadeOnDelete(false);

            HasOptional(task => task.Owner)
                .WithMany(owner => owner.TasksOwned)
                .HasForeignKey(task => task.OwnerId)
                .WillCascadeOnDelete(false);
        }
    }
    public class TestEFContext : DbContext {
        public IDbSet<User> us { get; set; }
        public IDbSet<Task> ts { get; set; }

        public TestEFContext(String cs)
            : base(cs) {
            Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
        }

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

            Configuration.LazyLoadingEnabled = false;

            modelBuilder.Configurations.Add(new TaskConfiguration());            
        }
    }

    class Program {
        static void Main(String[] args) {
            String cs = @"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";
            using (TestEFContext c = new TestEFContext(cs)) {
                User u1 = new User {
                    Id = Guid.NewGuid(),
                    UserName = "u1"
                };
                User u2 = new User {
                    Id = Guid.NewGuid(),
                    UserName = "u2"
                };
                c.us.Add(u1);
                c.us.Add(u2);
                Task t = new Task {
                    Id = Guid.NewGuid(),
                    ShortDescription = "t1",
                    Creator = u1,
                    Owner = u1
                };
                c.ts.Add(t);
                t = new Task {
                    Id = Guid.NewGuid(),
                    ShortDescription = "t2",
                    Creator = u2,
                    Owner = u1
                };
                c.ts.Add(t);
                c.SaveChanges();
            }

            using (TestEFContext c = new TestEFContext(cs)) {
                var user = c.us
                 .Include("TasksCreated")
                 .Include("TasksOwned")
                 .SingleOrDefault(u => u.UserName.Equals("u1", StringComparison.OrdinalIgnoreCase));
                foreach (Task t in user.TasksCreated) {
                    Console.WriteLine("{0} - {1} is owned by {2}, was created by {3} ", t.ShortDescription, t.Id, t.OwnerId, t.CreatorId);
                }
                Console.WriteLine("-----");

                foreach (Task t in user.TasksOwned) {
                    Console.WriteLine("{0} - {1} is owned by {2}, was created by {3} ", t.ShortDescription, t.Id, t.OwnerId, t.CreatorId);
                }
            }
        }
    }
}