如何在DTO中加载DTO?

时间:2015-01-08 05:09:47

标签: c# linq entity-framework entity-framework-6 asp.net-web-api2


问题:

我是EF和LINQ的新手,所以请耐心等待。

我正在尝试使用数据库第一种方法创建EF6模型。简单来说,我有2个数据库表tblUsertblMilkMan,它们在UserID列上具有外键关系。

为了避免循环引用和塑造实体数据,我为这两个模型创建了DTO类。

我让MilkManDTO类包含对UserDTO实例的引用。(这可能是愚蠢的,如果是这样,请指导我正确的方法)。我的目标是能够加载牛奶工和相关的用户数据

无论如何,在我的API调用中,当我尝试按ID加载MilkMan时,我不知道如何加载相关的UserDTO。我在网上找到了关于如何加载相关实体但没有相关DTO的示例。

数据库架构: ER Diagram

型号:

MilkMan模型和DTO:

namespace MilkMan.Models
{
    using System;
    using System.Collections.Generic;

    public partial class tblMilkMan
    {
        public int RecordID { get; set; }
        public int UserID { get; set; }
        public bool IsMyTurn { get; set; }
        public int RoundRobinOrder { get; set; }

        public virtual tblUser tblUser { get; set; }
    }

    public class MilkManDTO
    {
        public int RecordID { get; set; }
        public int UserID { get; set; }
        public bool IsMyTurn { get; set; }
        public int RoundRobinOrder { get; set; }

        public virtual UserDTO User { get; set; }
    }
}

用户模型和DTO:

public partial class tblUser
    {
        public tblUser()
        {
            this.tblMilkMen = new HashSet<tblMilkMan>();
        }

        public int UserID { get; set; }
        public string LogonName { get; set; }           
        public string Password { get; set; }           
        public int PasswordExpiresAfter { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        :
        // more fields
        :
        public virtual ICollection<tblMilkMan> tblMilkMen { get; set; }
    }

    public class UserDTO
    {
        public int UserID { get; set; }       
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

Web API控制器方法:

// GET api/MilkMan/5
        [ResponseType(typeof(MilkManDTO))]
        public async Task<IHttpActionResult> GettblMilkMan(int id)
        {
            //tblMilkMan tblmilkman = await db.tblMilkMen.FindAsync(id);

            MilkManDTO milkMan = await db.tblMilkMen.Select(b => new MilkManDTO()
            {
                RecordID = b.RecordID,
                UserID = b.UserID,
                IsMyTurn = b.IsMyTurn,
                RoundRobinOrder = b.RoundRobinOrder,
                User = //???? Error//

            }).SingleOrDefaultAsync(b => b.RecordID == id);


            if (milkMan == null)
            {
                return NotFound();
            }

            return Ok(milkMan);
        }

1 个答案:

答案 0 :(得分:1)

您可以嵌套new UserDTO并使用相同的初始化列表技术。

        MilkManDTO milkMan = await db.tblMilkMen.Select(b => new MilkManDTO()
        {
            RecordID = b.RecordID,
            UserID = b.UserID,
            IsMyTurn = b.IsMyTurn,
            RoundRobinOrder = b.RoundRobinOrder,
            User = new UserDTO {
               UserID = b.User.UserID,
               FirstName = b.User.FirstName,
               LastName = b.User.LastName,
            } 

        }).SingleOrDefaultAsync(b => b.RecordID == id);

如果没有关联的用户,则此代码可能在b.User.UserID上抛出空引用异常,因此User可能为null。您需要使用??合并,三元(b.User == null ? "DefaultFirstName" : b.User.FirstName)或省略整个参考User = (b.User == null ? (UserDTO)null : new UserDTO { ... })来处理此问题。 null's让这种事情变得有趣。

使用C#6,我们有空参考运算符.?,这使得它更加简洁。