使用LINQ进行连接后获取特定对象

时间:2017-10-19 16:40:54

标签: c# entity-framework linq

我正在尝试使用linq for join检索与实体框架中的表相关的特定类,其条件如下:

                var result = (from a in db.Persons
                             join b in db.Person_IDs on a.PersonId equals b.PersonId
                             where b.FaceId == faceId
                             select new
                             {
                                 PersonId = a.PersonId,
                                 Name = a.Name,
                                 Address = a.Address,
                                 Picture = a.Picture,
                                 City = a.City,
                                 Estate = a.Estate,
                                 Phone = a.Phone,
                                 CellPhone = a.CellPhone,
                                 BlackList = a.BlackList
                             }
                             ).FirstOrDefault();

我希望将“result”对象作为Person对象返回。在上面的例子中,我需要创建一个新的Person对象并添加来自结果的字段。

有可能吗?我尝试了一些方法并使用了一些样本和研究,但没有一种方法适合我。

谢谢!

更新1

好吧,经过一些阅读后,我发现这样做的最好方法是为我的Person对象创建一个DTO类,并在我的函数中返回这个DTO类,如下所示:

PersonDTO result = (from a in db.Persons
                             join b in db.Person_IDs on a.PersonId equals b.PersonId
                             where b.FaceId == faceId
                             select new PersonDTO
                             {
                                 PersonId = a.PersonId,
                                 Name = a.Name,
                                 Address = a.Address,
                                 Picture = a.Picture,
                                 City = a.City,
                                 Estate = a.Estate,
                                 Phone = a.Phone,
                                 CellPhone = a.CellPhone,
                                 BlackList = a.BlackList
                             }
                             ).FirstOrDefault();

            db.Dispose();

            return result;

好吧,它工作正常,但有一件事困扰我:为什么要创建另一个与EF类相同的类?为什么EF类不能这样使用?

我正在使用一个表,但是一个程序,例如,20个表将迫使我有20个实体类和20个实体DTO类!

作为初学者,我认为这种工作方式有点混乱或荒谬,采用传统方式(使用数据读取器,命令和连接)。即使是更官僚主义,它也不需要“重复”的对象。

有人可以提供这个答案吗?

更新2

根据要求:因为我没有看到在我的函数中返回的匿名类型,我尝试返回实体类(Person),但是当我这样做时,我在应用程序执行中遇到以下错误:

“无法在LINQ to Entities查询中构建实体或复杂类型'Models.Person'。”

所以这个解决方案是创建一个DTO类(或者一个viewmodel类,无论如何)。

3 个答案:

答案 0 :(得分:1)

如果您的数据库中有if(ScenarioContext.Current.Get<bool>("TestPassed")) return;个对象,并且您想要Person个对象,那么为什么要创建匿名类型呢?

为什么不尝试

Person

答案 1 :(得分:0)

你应该能够做到

var result = (from a in db.Persons 
    join b in db.Person_IDs on a.PersonId equals b.PersonId
    where b.FaceId == faceId
    select new Person
    { 
        PersonId = a.PersonId, 
        Name = a.Name, 
        Address = a.Address, 
        Picture = a.Picture, 
        City = a.City, 
        Estate = a.Estate, 
        Phone = a.Phone, 
        CellPhone = a.CellPhone, 
        BlackList = a.BlackList
    }).FirstOrDefault();

只要Person类可以访问,它的位置被导入,并且它具有与上述属性匹配的公共getter / setter,这应该可以工作。

如果您仍然遇到问题,请尝试为人员提供您的课程定义以及您可能会遇到的任何错误。

编辑:根据您看到的错误,我猜您正在尝试仅选择此实体上的某些属性。 EF实际上不会让你这样做。您可以选择整个实体(不指定属性,只选择a),也可以创建一个可以像我上面那样映射到的自定义DTO。

EF不喜欢不完整的映射,因为它会使状态混淆未来的模型修改。 See this answer here.因此,如果您想避免加载整个实体,请转到自定义DTO路线。

答案 2 :(得分:0)

你的代码是正确的!!寻求此解决方案,因为它具有最小的修改 只选择人

 person result = (from a in db.Persons
                             join b in db.Person_IDs on a.PersonId equals 
                             b.PersonId
                             where b.FaceId == faceId
                             select new person
                             {
                                 PersonId = a.PersonId,
                                 Name = a.Name,
                                 Address = a.Address,
                                 Picture = a.Picture,
                                 City = a.City,
                                 Estate = a.Estate,
                                 Phone = a.Phone,
                                 CellPhone = a.CellPhone,
                                 BlackList = a.BlackList
                             }
                             ).FirstOrDefault();