C # EF6 отображение не применяется при выборе - PullRequest
0 голосов
/ 28 апреля 2018

У меня проблема с отображением Fluent API в EF6. Все настроено, но по какой-то причине, когда я выбираю объект, ему не хватает дочерних объектов.

Давайте начнем с DbContext:

public partial class PMSContext : DbContext
{
    public PMSContext() : base(nameOrConnectionString: "PmsDb")
    {
        this.Configuration.ProxyCreationEnabled = false;
        this.Configuration.LazyLoadingEnabled = false;
    }

    public DbSet<Employee> employees { get; set; }
    public DbSet<Project> projects { get; set; }
    public DbSet<ProjectStep> projectSteps { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<Employee>().HasMany(e => e.Projects).WithMany(t => t.EmployeesWorkingOnProject).Map(m =>
        {
            m.MapLeftKey("EmployeeId");
            m.MapRightKey("ProjectId");
            m.ToTable("employee_project");
        });

        modelBuilder.Entity<ProjectStep>().HasRequired(p => p.Project).WithMany(s => s.ProjectSteps).Map(m => m.MapKey("Project")).WillCascadeOnDelete(true);
        //modelBuilder.Entity<Project>().HasMany(p => p.ProjectSteps).WithRequired(ps => ps.Project).WillCascadeOnDelete(true);

        modelBuilder.Entity<Employee>().HasOptional<Project>(e => e.LeaderOfProject).WithOptionalPrincipal(p => p.ProjectLeader).Map(m => m.MapKey("ProjectLeader"));

    }

    public Project FindProjectById(int id)
    {
        return this.projects.Find(id);
    }
}

Это почти все, что нужно для моей проблемы.

Я настроил в общей сложности 3 модельных класса:

[DataContract(Namespace = "Shared")]
public class Employee
{
    public Employee()
    {
        this.Projects = new List<Project>();
    }

    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public String Name { get; set; }

    [DataMember]
    public String JobDescription { get; set; }

    [DataMember]
    public String Department { get; set; }

    [DataMember]
    public String DirectDialing { get; set; }

    [DataMember]
    public bool Status { get; set; }

    public virtual Project LeaderOfProject { get; set; }

    [DataMember]
    public virtual List<Project> Projects { get; set; }
}

[DataContract(Namespace = "Shared")]
public class Project
{

    public Project()
    {
        this.EmployeesWorkingOnProject = new List<Employee>();
        this.ProjectSteps = new List<ProjectStep>();
    }

    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public String Titel { get; set; }

    [DataMember]
    public DateTime StartDate { get; set; }

    [DataMember]
    public DateTime EndDate { get; set; }

    [DataMember]
    public String Description { get; set; }

    [DataMember]
    public Employee ProjectLeader { get; set; }

    [DataMember]
    public bool Status { get; set; }

    [DataMember]
    public virtual List<Employee> EmployeesWorkingOnProject { get; set; }

    [DataMember]
    public virtual List<ProjectStep> ProjectSteps { get; set; }
}

[DataContract(Namespace = "Shared")]
[Table("project_step")]
public class ProjectStep
{
    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public String Description { get; set; }

    [DataMember]
    public DateTime StartDate { get; set; }

    [DataMember]
    public DateTime EndDate { get; set; }

    [DataMember]
    public Project Project { get; set; }
}

И соответствующая настройка базы данных:

enter image description here

Теперь к моей проблеме. Всякий раз, когда я выполняю метод FindProjectById, он возвращает правильный объект, но при этом отсутствует какая-либо ссылка на дочерние элементы. это означает, что

  • ProjectSteps
  • EmployeesWorkingOnProject
  • ProjectLeader

не установлены. Это также вызывает проблемы с моими методами удаления. Я предполагаю, что это ошибка в моем методе OnModelCreating, но я не уверен на 100%.

Может кто-нибудь сказать мне, чего мне не хватает, чтобы получить дочерние объекты?

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Вы отключили отложенную загрузку и прокси, но если вы не используете дочерние сущности .Include (), EF не знает, как их загрузить. Чтобы использовать .Include (), вам нужно использовать .SingleOrDefault (), а не Find. В противном случае вам нужно будет перейти в контекст для загрузки дочерних коллекций / ссылок.

Ваш FindProjectById () будет выглядеть примерно так:

var project = this.Projects.Include(x=>x.ProjectLeader)
  .Include(x=>x.EmployeesWorkingOnProject)
  .Include(x=>x.ProjectSteps)
  .SingleOrDefault(x=>x.ID == id); 
return project; 

Предостережение относительно использования SingleOrDefault и Find заключается в том, что Find будет искать локальное хранилище, затем идти в DB, ​​Single / First / и т. Д. Будет идти в DB. Это означает, что запрос выполняется каждый раз, когда Find может найти сущность в локальном хранилище памяти. если вы вставляете записи в контекст БД (и до сохранения изменений), поиск этого объекта не вернет объект, который находится в локальном хранилище, но еще не был зафиксирован в БД. (до SaveChanges ())

Обычно вы не хотите возвращать сущности вне области действия DbContext, поскольку прокси-серверы с отложенной загрузкой не будут работать, поэтому все, что вы не загрузите предварительно, будет #null. Обычно я полагаюсь на отложенное выполнение, возвращая IQueryable затем .Select () различные биты, которые меня интересуют, в классы PTO DTO / ViewModel.

0 голосов
/ 28 апреля 2018

Вы можете попробовать изменить отложенную загрузку на true , если хотите автоматически загружать дочерние объекты.

this.Configuration.LazyLoadingEnabled = true;

если отложенная загрузка ложна, вам нужно загрузить ссылку перед тем, как получить к ней доступ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...