Linq选择进入模型并设置属性

时间:2019-09-10 16:09:08

标签: c# linq asp.net-core entity-framework-core entity-framework-core-3.0

在.NET Core 2.X中,我可以在下面使用此代码:

var bookings = await db.Tasks
        .Where(c => c.ClientId == clientId && c.IsDeleted == false && c.Start > startOfThisMonth && c.End < endOfThisMonth)
        .OrderBy(x => x.Start)
        .Select(x => new SpecialTaskVm(new TaskViewModel(x, null))
        {
            client = x.Client,
            carer = x.Booking.SingleOrDefault(b => b.SlotNumber == 1).Carer,
            carer2 = x.Booking.SingleOrDefault(bk => bk.SlotNumber == 2).Carer
        })
        .ToListAsync();

.net core 3.X中的相同代码导致此错误:

  

System.InvalidOperationException:从“ VisitMemberInit”调用时,重写“ System.Linq.Expressions.NewExpression”类型的节点必须返回相同类型的非null值。或者,覆盖“ VisitMemberInit”并将其更改为不访问此类型的子项。

我真的可以按照上面的方法进行选择,因为每个模型都对某些属性进行了一些修改,并且每个模型分别在其他地方使用。

我还试图避免使用foreach,因为这似乎效率很低。

我尝试将需要设置的属性传递到模型中,然后像这样在模型中进行设置。发生相同的错误。

//This action method will return data for current month.
var startOfThisMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
var endOfThisMonth = new DateTime(DateTime.Now.Year, DateTime.Now.AddMonths(1).Month, 1);

var bookings = await db.Tasks
        .Where(c => c.ClientId == clientId && c.IsDeleted == false && c.Start > startOfThisMonth && c.End < endOfThisMonth)
        .OrderBy(x => x.Start)
        .Select(x => new SpecialTaskVm(new TaskViewModel(x, null))
        {
            client = x.Client,
            carer = x.Booking.SingleOrDefault(b => b.SlotNumber == 1).Carer,
            carer2 = x.Booking.SingleOrDefault(bk => bk.SlotNumber == 2).Carer
        })
        .ToListAsync();

我希望以List<SpecialTaskVm>的形式返回ClientCarerCarer2的任务列表。

1 个答案:

答案 0 :(得分:3)

在同一代码中使用构造函数和对象初始化语法有点不寻常,对我来说,这已经是代码的味道了。

如果我是您,我将创建一个仅从数据库获取值的中间列表,然后将数据投影到您的SpecialTaskVm对象中。例如:

// First get the data from the database in a simple form we can parse through later
var bookingData = await db.Tasks
        .Where(c => c.ClientId == clientId && c.IsDeleted == false && c.Start > startOfThisMonth && c.End < endOfThisMonth)
        .OrderBy(x => x.Start)
        .Select(x => new // Use an anonymous type
        {
            Client = x.Client,
            Carer = x.Booking.SingleOrDefault(b => b.SlotNumber == 1).Carer,
            Carer2 = x.Booking.SingleOrDefault(bk => bk.SlotNumber == 2).Carer
        })
        .ToListAsync();

// Now we massage the data into a format we can use
var bookings = bookingData
        .Select(x => new SpecialTaskVm(new TaskViewModel(x, null))
        {
            client = x.Client,
            carer = x.Carer,
            carer2 = x.Carer2
        })
        .ToList();

此外,我可能会建议更改SpecialTaskVm构造函数(或添加一个新的构造函数)以包括新字段。