C# 使用Linq查询将以下代码简化为一行程序
有两个表,用户表和费用表,具有一对多关系。因此,UserClass包含名为Expenses的ICollection类型的导航属性。我想要的是得到所有名为John的用户,并且只包括费用描述为午餐的费用。下面是我想到的。但我觉得有更好的办法。我想将其转换为:C# 使用Linq查询将以下代码简化为一行程序,c#,entity-framework,linq,lambda,C#,Entity Framework,Linq,Lambda,有两个表,用户表和费用表,具有一对多关系。因此,UserClass包含名为Expenses的ICollection类型的导航属性。我想要的是得到所有名为John的用户,并且只包括费用描述为午餐的费用。下面是我想到的。但我觉得有更好的办法。我想将其转换为: List<User> users = db.Users.Where(user => user.Name == "John").ToList(); foreach (User user in users)
List<User> users = db.Users.Where(user => user.Name == "John").ToList();
foreach (User user in users)
{
List<Expense> expenses = db.Expenses.Where(expense => expense.Description == "Lunch" && expense.AddedBy == user.Id).ToList();
user.Expenses = expenses;
}
型号:
PS:我不熟悉实体框架
谢谢。我的建议是使用投影查询
db.Users.Where(u => u.Name == "John")
.Where(u => u.Expenses.Any(e => e.Description == "Lunch")
.Select(u => new
{
u,
Expenses= u.Expenses.Where(e => e.Description == "Lunch")
});
名为u
的属性属于User
类型,它拥有所有费用,而另一个属性expenses
将只拥有为启动生成的费用
或使用
我的建议是使用投影查询
db.Users.Where(u => u.Name == "John")
.Where(u => u.Expenses.Any(e => e.Description == "Lunch")
.Select(u => new
{
u,
Expenses= u.Expenses.Where(e => e.Description == "Lunch")
});
名为u
的属性属于User
类型,它拥有所有费用,而另一个属性expenses
将只拥有为启动生成的费用
或使用
通常,将所选数据从数据库传输到本地进程是查询中较慢的部分之一。因此,最好不要获取比实际计划使用的属性更多的属性
您需要几个用户
,以及他们的部分或全部费用
。每个用户
都有一个主键Id
,每个费用
都有一个外键UserId
,您可以确定它等于其用户
的Id
如果您获取1000个用户,每个用户有1000个费用,那么您的方法将传输100万用户ID
,您已经知道其中的值。真是浪费
仅当您计划更改获取的值时才使用Include。如果没有,请使用选择`
要选择某些用户的某些属性及其费用
:
var result = myDbContext.Users // From the collection of all Users
.Where(user => user.Name == ...) // Select only those that have a name ...
.Select(user => new // from every remaining user make one new object
{
// Select only the properties you actually plan to use:
Id = user.Id,
Name = user.Name,
...
Expenses = user.Expenses
.Where(expense => expense.Description == ...)
.Select(expense => new
{
// again, select only the properties you plan to use
Id = expense.Id,
Description = expense.Description,
// not needed, you know it equals user.Id:
// UserId = expense.UserId
...
})
.ToList(),
});
有时您确实需要用户提供他们的费用
,例如,您需要将其用作过程的返回值。即使如此,也要使用选择和填充用例中真正需要的属性(或填充所有属性)
这样做的缺点是数据库表的布局会渗透到通信层中。如果数据库发生更改,所有调用者都需要更改,即使他们不使用新更改的属性。我的建议是在数据层之外使用您想要的类。这可能导致userswiththeiraddress
和UsersWithTheirExpenses
,甚至可能导致UsersWithTheirFoodExpenses
。如果用户获得了一个额外的列,如CountryCode
,则不必更改UsersWithTheirExpenses
。通常,将所选数据从数据库传输到本地进程是查询中较慢的部分之一。因此,最好不要获取比实际计划使用的属性更多的属性
您需要几个用户
,以及他们的部分或全部费用
。每个用户
都有一个主键Id
,每个费用
都有一个外键UserId
,您可以确定它等于其用户
的Id
如果您获取1000个用户,每个用户有1000个费用,那么您的方法将传输100万用户ID
,您已经知道其中的值。真是浪费
仅当您计划更改获取的值时才使用Include。如果没有,请使用选择`
要选择某些用户的某些属性及其费用
:
var result = myDbContext.Users // From the collection of all Users
.Where(user => user.Name == ...) // Select only those that have a name ...
.Select(user => new // from every remaining user make one new object
{
// Select only the properties you actually plan to use:
Id = user.Id,
Name = user.Name,
...
Expenses = user.Expenses
.Where(expense => expense.Description == ...)
.Select(expense => new
{
// again, select only the properties you plan to use
Id = expense.Id,
Description = expense.Description,
// not needed, you know it equals user.Id:
// UserId = expense.UserId
...
})
.ToList(),
});
有时您确实需要用户提供他们的费用
,例如,您需要将其用作过程的返回值。即使如此,也要使用选择和填充用例中真正需要的属性(或填充所有属性)
这样做的缺点是数据库表的布局会渗透到通信层中。如果数据库发生更改,所有调用者都需要更改,即使他们不使用新更改的属性。我的建议是在数据层之外使用您想要的类。这可能导致userswiththeiraddress
和UsersWithTheirExpenses
,甚至可能导致UsersWithTheirFoodExpenses
。如果用户获得了一个额外的列,比如CountryCode
,那么UsersWithTheirExpenses
就不需要更改。显示您的模型类您可以尝试在条件之前使用Include方法吗我认为您不能以这种方式包括导航属性的一些实例.Include(user=>user.Expenses)
应该可以though@mshwf我添加了一个image@Md.AbdulAlim仍然相同如何显示您的模型类您可以尝试在where condition之前使用Include方法吗?我不认为您可以通过这种方式仅包含导航属性的某些实例.Include(user=>user.Expenses)
应该可以though@mshwf我添加了一个image@Md.AbdulAlim仍然相同的费用
应该是费用
,您在末尾遗漏了一个)
,并且。其中
不返回一个bool
,对吗?这仍然包括至少有一项费用为Description==“午餐”
的用户的所有费用。我认为OP只需要“John”
用户的“午餐”
费用。(从问题中,强调我的:“获取所有名为John的用户,只包括费用描述为午餐的费用”)EF+的事情很有趣,我将为此+1。仍然)代码>结尾处缺少;)谢谢你的评论。:)@ThierryV Entity Framework Plus的工作非常出色。谢谢。费用
应该是费用
,您在最后错过了一个)
,并且。其中
不返回bool
,对吗?这仍然包括用户在中至少有一项费用的所有费用
var result = myDbContext.Users // From the collection of all Users
.Where(user => user.Name == ...) // Select only those that have a name ...
.Select(user => new // from every remaining user make one new object
{
// Select only the properties you actually plan to use:
Id = user.Id,
Name = user.Name,
...
Expenses = user.Expenses
.Where(expense => expense.Description == ...)
.Select(expense => new
{
// again, select only the properties you plan to use
Id = expense.Id,
Description = expense.Description,
// not needed, you know it equals user.Id:
// UserId = expense.UserId
...
})
.ToList(),
});
var result = myDbContext.Users
.Where(user => user.Name == ...)
.Select(user => new User()
{
// Select only the properties you actually plan to use:
Id = user.Id,
Name = user.Name,
...
Expenses = user.Expenses
.Where(expense => expense.Description == ...)
.Select(expense => new Expense()
{
// again, select only the properties you plan to use
Id = expense.Id,
Description = expense.Description,
...
})
.ToList(),
});