首页 > 解决方案 > Asp.net - 核心 - 声明未设置导航属性的 Dto

问题描述

我想使用一个存储库选项,它首先检索所有记录,但也检索包含,然后使用 where 子句根据给定的 Id 选择一个客户端。我还想通过包含包含该实体的所有注释..客户..以及它的地址和工作,但是如果我 尝试AddressAddressDtoClientNotesClientNotesDto

“数据为 Null。无法对 Null 值调用此方法或属性。”

好的,这里是加载客户端的客户端实体......

using JobsLedger.INTERFACES;

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace JobsLedger.DATA.ENTITIES
{
#nullable enable
    public class Client : IEntityBase, IAuditedEntityBase
    {
        public Client()
        {
            ClientNotes = new List<Note>();
            Jobs = new List<Job>();
        }

        [Key]
        public int Id { get; set; }
        public string ClientNo { get; set; } = default!;
        public bool Company { get; set; }
        public string CompanyName { get; set; } = null!;
        public string Abn { get; set; } = null!;
        public bool IsWarrantyCompany { set; get; }
        public bool RequiresPartsPayment { set; get; }
        public string ClientFirstName { get; set; } = null!;
        public string ClientLastName { get; set; } = null!;
        public string Email { get; set; } = null!;
        public string MobilePhone { get; set; } = null!;
        public string Phone { get; set; } = null!;
        public string Address1 { get; set; } = null!;
        public string Address2 { get; set; } = null!;
        public string BankName { get; set; } = null!;
        public string BankBSB { get; set; } = null!;
        public string BankAccount { get; set; } = null!;
        public bool Active { get; set; }
        public DateTime? DateDeActivated { get; set; }
        public bool Activity { get; set; }

        // One warranty company client to a job.
        public int? WarrantyCompanyId { get; set; }

        public virtual Job WarrantyCompany { get; set; } = null!;

        // One suburb to a client.
        public int? SuburbId { get; set; }
        public virtual Suburb Suburb { get; set; } = null!;

        // If its a warranty company then we simply link it one to one to the brand id.
        public virtual Brand Brand { get; set; } = null!;

        // Multiple notes for each client.
        public virtual ICollection<Note> ClientNotes { get; }

        // Multiple jobs for each client.
        public virtual ICollection<Job> Jobs { get; set; }

        public virtual ICollection<Job> WarrantyCompanyJobs { get; } = default!;
    }
#nullable disable
}

这是clientDto..

using System.Collections.Generic;
using JobsLedger.MODELS.API.App.Job;
using JobsLedger.MODELS.Common.Address;
using JobsLedger.MODELS.Common.Notes;

using System.ComponentModel.DataAnnotations;
using System.Linq;
using Newtonsoft.Json;

namespace JobsLedger.MODELS.API.App.Client
{
    public class ClientDetailsDto
    {

        public ClientDetailsDto()
        {
            Address = new AddressDto();
            //ClientNotes = new List<ClientNoteDto>();
            //ClientJobs = new List<ClientJobDto>();
        }
        [Key]
        public int Id { get; set; }
        public string ClientNo { get; set; }
        public bool Company { get; set; }
        public bool IsWarrantyCompany { set; get; }
        public string CompanyName { get; set; }
        public string ClientFirstName { get; set; }
        public string ClientLastName { get; set; }
        public string MobilePhone { get; set; }
        public string DeActivated { get; set; }
        public string CreatedOn { get; set; }
        public string CreatedBy { get; set; }
        public string ModifiedOn { get; set; }
        public string ModifiedBy { get; set; }

        public int SuburbId { get; set; }
        public AddressDto Address { get; set; }
        public ICollection<ClientJobDto> ClientJobs { get; set; }
        public IQueryable<ClientNoteDto> ClientNotes { get; set; }
    }
}

是的,有一些属性,但它相当简单。

在执行“Where”子句获取单个客户端之前,存储库使用此方法获取所有客户端。

    public virtual IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
    {
        IQueryable<T> query = _context.Set<T>();
        foreach (var includeProperty in includeProperties)
        {
            query = query.Include(includeProperty);
        }

        return query;
    }

现在请记住,我得到了实际的客户端及其实际投影到 DTO。但是,如果我将项目设置为ClientDto它可以工作.. 我会为单个客户取回数据。

如果取消注释地址和ClientNotes预测它会失败并出现上述错误。

我的印象是,通过包含,我实际上应该得到关联或相关的实体,而我不是。是不是因为懒加载等等。。

这是声明:

var result = ClientDATARepository?.AllIncluding(c => c.Jobs, c => c.ClientNotes, c => c.Suburb).Where(x => x.Id == id).Select(fetchedClient =>
            new ClientDetailsDto {
                Id = fetchedClient.Id,
                ClientNo = fetchedClient.ClientNo,
                Company = fetchedClient.Company,
                IsWarrantyCompany = fetchedClient.IsWarrantyCompany,
                CompanyName = fetchedClient.CompanyName,
                ClientFirstName = fetchedClient.ClientFirstName,
                ClientLastName = fetchedClient.ClientLastName,
                MobilePhone = fetchedClient.MobilePhone,
                DeActivated = fetchedClient.DateDeActivated.HasValue ? "true" : "false",
                CreatedOn = EF.Property<DateTime>(fetchedClient, "CreatedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
                ModifiedOn = EF.Property<DateTime>(fetchedClient, "ModifiedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),

                Address =    // ..I believe it fails here.
                    new AddressDto {
                        Address1 = fetchedClient.Address1,
                        Address2 = fetchedClient.Address2,
                        SuburbId = fetchedClient.Suburb.Id,
                        SuburbName = fetchedClient.Suburb.SuburbName,
                        StateShortName = fetchedClient.Suburb.State.StateShortName,
                        Postcode = fetchedClient.Suburb.PostCode,
                    },

                ClientNotes = fetchedClient.ClientNotes.Select(fetchedClientNote =>  // ..and here..
                    new ClientNoteDto {
                        id = fetchedClientNote.Id,
                        Details = fetchedClientNote.Details,
                        NoteType = NoteTypeDATARepository.GetAll().FirstOrDefault(x => x.Id == fetchedClientNote.NoteTypeId).Name,
                        CreatedOnDate = EF.Property<DateTime>(fetchedClientNote, "CreatedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
                        CreatedOnTime = EF.Property<DateTime>(fetchedClientNote, "CreatedOn").ToString("h:mm tt", CultureInfo.CurrentCulture),

                        ModifiedOnDate = EF.Property<DateTime>(fetchedClientNote, "ModifiedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
                        ModifiedOnTime = EF.Property<DateTime>(fetchedClientNote, "ModifiedOn").ToString("h:mm tt", CultureInfo.CurrentCulture),    
                });

正如我在尝试加载时提到的AddressClientNotes它抛出上述错误说数据不能为空..

我想知道为什么我无法加载AddressClientNotes更重要的是如何制作它,所以我确实加载了这些.. 此外.. 为什么我不能这样做并且仍然将它作为 IQueryable?

标签: c#asp.net-coreentity-framework-core

解决方案


推荐阅读