C# 创建匿名类型时如何使用临时本地数据?
我从C# 创建匿名类型时如何使用临时本地数据?,c#,linq,anonymous-types,C#,Linq,Anonymous Types,我从EF中获取一些实体,我迭代并创建匿名类型对象,例如: var payments = ctx.Payments.ToList(); var data = ctx.Activities.OrderBy(p => p.ID).ToList().Select(p => new { ID = p.ID, Date = p.Date?.ToString("dd/MM/yyyy"), PaymentMethod = p.PaymentMethods != null ?
EF
中获取一些实体,我迭代并创建匿名类型对象,例如:
var payments = ctx.Payments.ToList();
var data = ctx.Activities.OrderBy(p => p.ID).ToList().Select(p => new
{
ID = p.ID,
Date = p.Date?.ToString("dd/MM/yyyy"),
PaymentMethod = p.PaymentMethods != null ? p.PaymentMethods.Description : "",
ActivityStatusID = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 0 ? 1 : .. // I need some other check
}).ToList();
现在,我想在设置值之前检查几次payments.Where(q=>q.ActivityID==p.ID&&!q.paymed).Count()
例如:
ActivityStatusID = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 0 ? 1 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 1 ? 8 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() > 1 ? 10 : 87
var payments = ctx.Payments.ToList();
var data = (
from p in ctx.Activities.ToList()
orderby p.ID
let paymentCount = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count()
select new
{
ID = p.ID,
Date = p.Date?.ToString("dd/MM/yyyy"),
PaymentMethod = p.PaymentMethods != null ? p.PaymentMethods.Description : "",
ActivityStatusID = paymentCount == 0 ? 1 : .. // I need some other check
}
).ToList();
payments.Count(q => q.ActivityID == p.ID && !q.Paid)
是否有任何方法进行付款。其中(q=>q.ActivityID==p.ID&&!q.Paid)。Count()每个
p
一次,然后评估条件?我会将查询从lambda表达式更改为普通查询。然后使用let
语法为每次迭代设置一个变量。大概是这样的:
ActivityStatusID = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 0 ? 1 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 1 ? 8 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() > 1 ? 10 : 87
var payments = ctx.Payments.ToList();
var data = (
from p in ctx.Activities.ToList()
orderby p.ID
let paymentCount = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count()
select new
{
ID = p.ID,
Date = p.Date?.ToString("dd/MM/yyyy"),
PaymentMethod = p.PaymentMethods != null ? p.PaymentMethods.Description : "",
ActivityStatusID = paymentCount == 0 ? 1 : .. // I need some other check
}
).ToList();
payments.Count(q => q.ActivityID == p.ID && !q.Paid)
顺便说一句,你也可以做不同的部分。这:
payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count()
你可以这样写:
ActivityStatusID = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 0 ? 1 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 1 ? 8 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() > 1 ? 10 : 87
var payments = ctx.Payments.ToList();
var data = (
from p in ctx.Activities.ToList()
orderby p.ID
let paymentCount = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count()
select new
{
ID = p.ID,
Date = p.Date?.ToString("dd/MM/yyyy"),
PaymentMethod = p.PaymentMethods != null ? p.PaymentMethods.Description : "",
ActivityStatusID = paymentCount == 0 ? 1 : .. // I need some other check
}
).ToList();
payments.Count(q => q.ActivityID == p.ID && !q.Paid)
我将把查询从lambda表达式更改为普通查询。然后使用
let
语法为每次迭代设置一个变量。大概是这样的:
ActivityStatusID = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 0 ? 1 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 1 ? 8 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() > 1 ? 10 : 87
var payments = ctx.Payments.ToList();
var data = (
from p in ctx.Activities.ToList()
orderby p.ID
let paymentCount = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count()
select new
{
ID = p.ID,
Date = p.Date?.ToString("dd/MM/yyyy"),
PaymentMethod = p.PaymentMethods != null ? p.PaymentMethods.Description : "",
ActivityStatusID = paymentCount == 0 ? 1 : .. // I need some other check
}
).ToList();
payments.Count(q => q.ActivityID == p.ID && !q.Paid)
顺便说一句,你也可以做不同的部分。这:
payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count()
你可以这样写:
ActivityStatusID = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 0 ? 1 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() == 1 ? 8 : payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count() > 1 ? 10 : 87
var payments = ctx.Payments.ToList();
var data = (
from p in ctx.Activities.ToList()
orderby p.ID
let paymentCount = payments.Where(q => q.ActivityID == p.ID && !q.Paid).Count()
select new
{
ID = p.ID,
Date = p.Date?.ToString("dd/MM/yyyy"),
PaymentMethod = p.PaymentMethods != null ? p.PaymentMethods.Description : "",
ActivityStatusID = paymentCount == 0 ? 1 : .. // I need some other check
}
).ToList();
payments.Count(q => q.ActivityID == p.ID && !q.Paid)
人们建议将您的查询转换为查询语法,这将使您能够使用
let
语句创建一个可以保存count的变量
如果您调查让
做什么,它会在结果中添加一列值。结果中的每一行在此列中具有相同的let值
将查询保持在方法语法中
如果要使查询保持方法语法,只需向匿名类型添加计数:
var result = ctx.Activities
.OrderBy(p => p.ID)
.Select(p => new
{
Id = p.Id,
Date = p.Date?.ToString("dd/MM/yyyy"),
PaymentMethod = p.PaymentMethods != null ? p.PaymentMethods.Description : "",
PaidCount = payments
.Where(q => q.ActivityID == p.ID && !q.Paid)
.Count();
})
.Select(p => new
{
Id = p.Id,
Date = p.Date,
ActivityStatusId =
{
// count == 0 => 1
// count == 1 => 8
// count > 1 => 10
// count < 0 => 87
if (p.PaidCount < 0) return 87;
switch (p.PaidCount)
{
case 0:
return 0;
case 1:
return 8;
default:
return 10;
}
},
});
AsEnumerable比ToList更有效,尤其是当您不需要同时使用所有项目时。例如,如果以FirstOrDefault结束,或者只取(5),那么将所有项移动到本地内存将是一种浪费
最后:通过一些尝试,您可以摆脱switch语句,从而允许DBMS计算ActivityStatusId。但是,由于选择源数据以及将所选数据传输到本地内存是整个查询过程中较慢的部分,因此我怀疑这是否会缩短执行时间。切换肯定会使您的需求更具可读性,尤其是当您的数字1/8/87被放入枚举时。人们建议将您的查询转换为查询语法,这将使您能够使用
let
语句创建一个可以保存计数的变量
如果您调查让
做什么,它会在结果中添加一列值。结果中的每一行在此列中具有相同的let值
将查询保持在方法语法中
如果要使查询保持方法语法,只需向匿名类型添加计数:
var result = ctx.Activities
.OrderBy(p => p.ID)
.Select(p => new
{
Id = p.Id,
Date = p.Date?.ToString("dd/MM/yyyy"),
PaymentMethod = p.PaymentMethods != null ? p.PaymentMethods.Description : "",
PaidCount = payments
.Where(q => q.ActivityID == p.ID && !q.Paid)
.Count();
})
.Select(p => new
{
Id = p.Id,
Date = p.Date,
ActivityStatusId =
{
// count == 0 => 1
// count == 1 => 8
// count > 1 => 10
// count < 0 => 87
if (p.PaidCount < 0) return 87;
switch (p.PaidCount)
{
case 0:
return 0;
case 1:
return 8;
default:
return 10;
}
},
});
AsEnumerable比ToList更有效,尤其是当您不需要同时使用所有项目时。例如,如果以FirstOrDefault结束,或者只取(5),那么将所有项移动到本地内存将是一种浪费
最后:通过一些尝试,您可以摆脱switch语句,从而允许DBMS计算ActivityStatusId。但是,由于选择源数据以及将所选数据传输到本地内存是整个查询过程中较慢的部分,因此我怀疑这是否会缩短执行时间。切换肯定会使您的需求更具可读性,特别是如果您的数字1/8/87被放入枚举中。如果您使用的是查询语法而不是方法语法,则可以使用
let
。如果要坚持方法语法,必须引入另一个匿名类型,该类型具有payments
和一个值为payments.Where(q=>q.ActivityID==p.ID&&!q.payment).Count()
如果使用查询语法而不是方法语法,则可以使用let
。如果您想坚持使用方法语法,则必须引入另一个匿名类型,该类型具有payments
和一个值为payments的属性。其中(q=>q.ActivityID==p.ID&&!q.paymed)。Count()
尝试了您的建议。有些麻烦。第一个:不能执行Date=p.Date?.ToString(“dd/MM/yyyy”)
(表达式树lambda不能包含null传播运算符)。所以我把它改成了Date=p.Date.HasValue?p、 Date.Value.ToString(“dd/MM/yyyy”):null,
,但现在“LINQ to Entities不识别方法'System.String ToString(System.String)'方法,并且此方法无法转换为存储表达式。”我想您忘记了ctx.Activities.ToList()
?另外,为什么我不能将let
用于Lambda?@markzzz:True我最后忘记了.ToList()。我已经更新了answer@markzzz:因为您没有“查询主体”来设置“让您的建议输入”。有些麻烦。第一个:不能执行Date=p.Date?.ToString(“dd/MM/yyyy”)
(表达式树lambda不能包含null传播运算符)。所以我把它改成了Date=p.Date.HasValue?p、 Date.Value.ToString(“dd/MM/yyyy”):null,
,但现在“LINQ to Entities不识别方法'System.String ToString(System.String)'方法,并且此方法无法转换为存储表达式。”我想您忘记了ctx.Activities.ToList()
?另外,为什么我不能将let
用于Lambda?@markzzz:True我最后忘记了.ToList()。我已经更新了answer@markzzz:因为您没有“查询主体”来设置入口