C# 无法在实体框架中获取导航属性

C# 无法在实体框架中获取导航属性,c#,wpf,entity-framework,linq,mvvm,C#,Wpf,Entity Framework,Linq,Mvvm,我正在Visual Studio 2015中构建一个WPF MVVM Light应用程序,使用Entity Framework 6连接到SQL Server 2008 R2数据库。需要搜索的两个表是:PersonnelTech及其子表PersonnelTechCostCenter PersonnelTech可以有任意数量的PersonnelTech成本中心记录,因此PersonnelTech ID是子表中的外键 这是父表: CREATE TABLE [dbo].[PersonnelTech] (

我正在Visual Studio 2015中构建一个WPF MVVM Light应用程序,使用Entity Framework 6连接到SQL Server 2008 R2数据库。需要搜索的两个表是:PersonnelTech及其子表PersonnelTechCostCenter

PersonnelTech可以有任意数量的PersonnelTech成本中心记录,因此PersonnelTech ID是子表中的外键

这是父表:

CREATE TABLE [dbo].[PersonnelTech]
(
    [personnelTechId] [int] IDENTITY(1,1) NOT NULL,
    [name] [nvarchar](95) NOT NULL,
    [email] [nvarchar](95) NOT NULL,
    [isActive] [bit] NOT NULL 
        CONSTRAINT [DF_PersonnelTech_isActive]  DEFAULT ((1)),
    [createdDate] [datetime] NOT NULL CONSTRAINT [DF_PersonnelTech_createdDate]  DEFAULT (getdate()),

    CONSTRAINT [PK_PersonnelTech] 
        PRIMARY KEY CLUSTERED ([personnelTechId] ASC)
                WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                      IGNORE_DUP_KEY = OFF, 
                      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
)
这是孩子:

CREATE TABLE [dbo].[PersonnelTechCostCenter]
(
    [personnelTechCostCenterId] [int] IDENTITY(1,1) NOT NULL,
    [personnelTechId] [int] NOT NULL,
    [costCenter] [nvarchar](50) NOT NULL,
    [organizationalUnit] [nvarchar](50) NULL,
    [isActive] [bit] NOT NULL 
        CONSTRAINT [DF_PersonnelTechCostCenter_isActive]  DEFAULT ((1)),
    [createdDate] [datetime] NOT NULL 
        CONSTRAINT [DF_PersonnelTechCostCenter_createdDate]  DEFAULT (getdate()),

    CONSTRAINT [PK_PersonnelTechCostCenter] 
        PRIMARY KEY CLUSTERED ([personnelTechCostCenterId] ASC)
           WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                 IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                 ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[PersonnelTechCostCenter] WITH CHECK 
  ADD CONSTRAINT [FK_PersonnelTechCostCenter_PersonnelTech] 
      FOREIGN KEY([personnelTechId])
      REFERENCES [dbo].[PersonnelTech] ([personnelTechId])

ALTER TABLE [dbo].[PersonnelTechCostCenter] 
   CHECK CONSTRAINT [FK_PersonnelTechCostCenter_PersonnelTech]
在我的方法中,我尝试使用LINQ获取父记录和子记录,并用它们填充一些ObservableCollection视图模型:

using (var db = new MyEntities())
{
    var query = (from pt in db.PersonnelTeches
                 where pt.isActive.Equals(true)
                 orderby pt.name
                 select new PersonnelTechViewModel
                        {
                            PersonnelTechId = pt.personnelTechId,
                            Name = pt.name,
                            Email = pt.name,
                            IsActive = pt.isActive,
                            CreatedDate = pt.createdDate,
                            CostCenterVms = new ObservableCollection<PersonnelTechCostCenterViewModel>(pt.PersonnelTechCostCenters.Where(x => x.isActive)
                        .Select(
                        ptcc => new PersonnelTechCostCenterViewModel
                        {
                            PersonnelTechCostCenterId = ptcc.personnelTechCostCenterId,
                            PersonnelTechId = ptcc.personnelTechId,
                            CostCenter = ptcc.costCenter,
                            OrganizationalUnit = ptcc.organizationalUnit,
                            IsActive = ptcc.isActive,
                            CreatedDate = ptcc.createdDate
                        }).OrderBy(x => x.CostCenter).DefaultIfEmpty())
        }).ToList();
    return await Task.Run(() => new ObservableCollection<PersonnelTechViewModel>(query));
}
然而,这在返回声明中被放大,并表示:

LINQ to实体中只支持无参数构造函数和初始值设定项


其他帖子说你需要把第一部分变成它自己的部分;最后,您需要执行另一个操作。选择以从导航属性填充。我不知道如何做到这一点。

好的,首先我不知道你为什么要做一个选择,似乎要从技术人员到他们的中心。EF应该通过其上下文操作为您执行所有连接。让我们把它变得更简单,比如说

我有一个表tePerson,其中包含字段:PersonId、FirstName、LastName、OrderId。 此表包含值

1   Brett   X 1
2   Emily   X 2
4   Ryan    Y 1
10  Mark    Z 1 
OrderId是表的外键,该表只有两个字段:OrderId和Description

1   Shirt
2   Dress
设置实体框架时,您需要设置存在的上下文,然后将对象从生成的POCO对象的T4模板实现为可用的形式。通常,您会在名为“MyEntities.edmx”的类下面看到上下文“MyEntities.context.tt”和“MyEntities.tt”。实体上下文通常包含对所有POCO对象的引用,而在另一个上下文下,您的POCO被创建为与数据库中的内容类似的.NET匹配项。但是,如果您有一个外键,您应该让实体创建一个关系并为您进行连接。因此,在我为tePerson教授的Poco课程中,我看到:

public partial class tePerson
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Nullable<int> OrderId { get; set; }

    public virtual teOrder teOrder { get; set; }
}
我只是用“ToList”实现了一个对象,然后我用lambda“select”遍历了一个结构,通过外键得到了它的子对象和它们的子对象,然后用“ToList”实现了这个结构

public partial class teOrder
{
    public teOrder()
    {
        this.tePersons = new HashSet<tePerson>();
    }

    public int OrderId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<tePerson> tePersons { get; set; }
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Timers;
using System.Data;
using System.Linq;
using System.Collections.ObjectMode;

static void Main(string[] args)
{
  using (var context = new TesterEntities())
  {
    var peopleWithOrderOfOne = context.tePersons.Where(x => x.OrderId == 1);

    // Go down to get the orders for Brett, Ryan, and Mark.  I am realizing an object that is a foreign key merely by selecting the complex object.
    // In this case x.teOrder is a POCO class mapped to another POCO class
    var observable = new ObservableCollection<teOrder>(peopleWithOrderOfOne.ToList().Select(x => x.teOrder).ToList());

    // display it
    observable.ToList().ForEach(x => Console.WriteLine($"{x.Description}"));

    //If you want to fully realize new objects you need to make them concrete by doing a select followed by a toList to materialize them, else they are not realized yet.
    // THis WILL NOT WORK:
    //var madeupPeopleAndOrders = context.tePersons
    //  .Select(x =>
    //    new tePerson
    //    {
    //      FirstName = x.FirstName,
    //      LastName = x.LastName,
    //      teOrder = new teOrder
    //      {
    //        OrderId = x.OrderId.Value,
    //        Description = x.teOrder.Description
    //      }
    //    });

    // THis WILL WORK:
    var madeupPeopleAndOrders = context.tePersons
      .ToList()
      .Select(x =>
        new tePerson
        {
          FirstName = x.FirstName,
          LastName = x.LastName,
          teOrder = new teOrder
          {
            OrderId = x.OrderId.Value,
            Description = x.teOrder.Description
          }
        });

    madeupPeopleAndOrders.ToList().ForEach(x => Console.WriteLine($"{x.FirstName} {x.LastName} {x.teOrder.Description}"));
  }

  Console.ReadLine();
}
context.tableName.toList().Select(x => x.childobject.itschildobject.value).ToList()