简体   繁体   English

我如何在 LINQ 中使用带条件的计数

[英]How can i use Count with condition in LINQ

I wanted to get the number of times that , the customer participant our events.我想获得客户参与我们活动的次数。 So the sql code is suppose to be like this.所以sql代码应该是这样的。

SELECT COUNT(CustomerID)
FROM EventsParticipants
WHERE (CustomerID == Session["CustomerID"]);

And LINQ code is like this is I am not mistaken, it will return the value of the Count() right.而 LINQ 代码是这样的,我没看错,它会正确返回Count()的值。

var recordcount = db.EventParticipants.Where(Session["CustomerID] == db.EventParticipants.CustomerID).Count();

But it return this error code但它返回此错误代码

'DbSet<EventParticipants>' does not contain a definition for 'CustomerID' and no accessible extension method 'CustomerID' accepting a first argument of type 'DbSet<EventParticipants>' could be found (are you missing a using directive or an assembly reference?)    LeafLife

You need to pass a lambda that takes the entity and returns a bool , like this您需要传递一个接受实体并返回bool的 lambda ,就像这样

var id = Session["CustomerID"];
var recordcount = db.EventParticipants.Where(x => x.CustomerID == id).Count();

Note you'll also want to put the id into a separate variable as EF will not be able to translate Session into SQL.请注意,您还需要将 id 放入一个单独的变量中,因为 EF 将无法将Session转换为 SQL。

You need to assign the Session["CustomerID"] value to a variable before you use that in the EF Linq query.在 EF Linq 查询中使用该值之前,您需要将Session["CustomerID"]值分配给一个变量。

Also, You need not filter and then get the count you can mention the condition inside the LINQ count function directly.此外,您无需过滤然后获取计数,您可以直接在 LINQ 计数函数中提及条件。 Please refer below请参考以下

var id = Convert.ToInt32(Session["CustomerID"]); // Assuming this as int
var recordcount = db.EventParticipants.Count(x => x.CustomerID == id);

Try this instead:试试这个:

var id = Session["CustomerID"];    
var recordcount = db.EventParticipants.Count(t=> id == t.CustomerID);

When you do Count later, it will do count in memory after getting all results.当你稍后进行Count ,它会在获得所有结果后在内存中进行计数。 Essentially it will do SELECT * FROM EventsParticipants WHERE (CustomerID == Session["CustomerID"]);本质上它会做SELECT * FROM EventsParticipants WHERE (CustomerID == Session["CustomerID"]); and then in memory it will find how many items are there.然后在内存中它会找到有多少项目。 (Don't do this) (不要这样做)

If you do what is shown above will create the same query as you intended and will be faster.如果您执行上面显示的操作,将创建与您预期相同的查询,并且速度会更快。

Lambda Expressions Lambda 表达式

Whenever you see in LINQ a parameter in the format of Func<...> , or Expressions<Func<...>> , you need to provide a function with the correct input parameters and the correct return value.每当您在 LINQ 中看到Func<...>Expressions<Func<...>>格式的参数时,您都需要提供具有正确输入参数和正确返回值的函数。

Func<Ta, Tb, Tc> represents any method that has two input parameters and a return value. Func<Ta, Tb, Tc>表示任何具有两个输入参数和一个返回值的方法。 The first parameter is of type Ta, the second parameter is of type Tb.第一个参数是 Ta 类型,第二个参数是 Tb 类型。 The returnvalue is of type Tc.返回值的类型为 Tc。 The following methods will do:以下方法可以做到:

bool String.Equals(string x, string y);
Shop FindShop(Product product, decimal maximumPrice);

Of course the types must match the other types in your generic LINQ method.当然,这些类型必须与泛型 LINQ 方法中的其他类型相匹配。

For example, if you have Customers and Orders , and you want to create PackingSlips , you might want to use Enumerable.Join for this.例如,如果您有CustomersOrders ,并且您想要创建PackingSlips ,您可能想要为此使用Enumerable.Join

public static IEnumerable<TResult> Join<TOuter,TInner,TKey,TResult> (
    this IEnumerable<TOuter> outer,
    IEnumerable<TInner> inner,
    Func<TOuter,TKey> outerKeySelector,
    Func<TInner,TKey> innerKeySelector,
    Func<TOuter,TInner,TResult> resultSelector);

The actual type of TOuter is Customer , the actual type of TInner is Order. TOuter的实际类型Customer的实际类型TInner是秩序。 To produce the result you use parameter resultSelector:要生成结果,请使用参数 resultSelector:

Func<TOuter,TInner,TResult> resultSelector

In your case:在你的情况下:

Func<Customer, Order , PackingSlip> resultSelector

This means, that you have to provide a function that will have two input parameters: Customer and Order, and that returns a PackingSlip:这意味着,您必须提供一个具有两个输入参数的函数:Customer 和 Order,并返回一个 PackingSlip:

PackingSlip CreatePackingSlip(Customer customer, Order order);

So you will use the Join as follows:因此,您将按如下方式使用 Join:

IEnumerable<Customer> customers = ...
IEnumerable<Order> orders = ...
IEnumerable<PackingSlip> packingSlips = customers.Join(orders,
    ... // parameter keySelector, see later,

    // parameter resultSelector:
    CreatePackingSlip);

This will do, but it is not very handy, and thus will not be used very often.这可以,但不是很方便,因此不会经常使用。 For instance, what if you have the following method:例如,如果您有以下方法怎么办:

PackingSlip CreatePackingSlip(Order order, Customer customer);

For this the lambda expression is created.为此,创建了 lambda 表达式。 It has the format of:它的格式如下:

(...) => ...

This means: create a Func<...> , or an Action<with the input parameters between the brackets and the code that is after the arrow.这意味着:创建一个Func<...>或一个 Action< ,其中输入参数位于括号和箭头后面的代码之间。 For example例如

Func<Customer, Order, PackingSlip> resultSelector

(customer, order) => CreatePackingSlip(order, customer);

is the same as:是相同的:

PackingSlip CreatePackingSlip(Customer customer, Order order)
{
    return CreatePackingSlip(order, customer); // call the other overload
}

But in fact you can use any code block for this:但实际上,您可以为此使用任何代码块:

(customer, order) => new PackingSlip()
                     {
                          Customer = customer,
                          Order = Order,
                     });

Or even a small piece of Code:甚至一小段代码:

(customer, order) => 
{
    string addressLines = this.CreateAddressLines(customer);
    var orderLines = this.CreateOrderLines(order);
    decimal totalPrice = this.CalculateTotalPrice(order);

    PackingSlip packingSlip = new PackingSlip()
    {
       Address = addressLines,
       OrderLines = orderLines,
       TotalPrice = totalPrice,
    };
    return packingSlip;
});

Anything will do, as long as the part between the brackets (..., ...) mention the arguments of the Func<...> in the correct order, and the part after the => returns the return value of the func.任何事情都可以,只要括号(..., ...)之间的部分以正确的顺序提及Func<...>的参数,并且=>后面的部分返回函数的返回值功能

I promised the parameters keySelector of the Join above.我答应了上面Join的参数keySelector They are use to specify what you want to join on.它们用于指定您要加入的内容。 In this case: we want to match the primary key Customer.Id with the foreign key Order.CustomerId :在这种情况下:我们希望将主键Customer.Id与外键Order.CustomerId

IEnumerable<Customer> customers = ...
IEnumerable<Order> orders = ...

IEnumerable<PackingSlip> packingSlips = customers.Join(orders,
    customer => customer.Id,      // from every customer take the primary key in Id
    order => order.CustomerId,    // from every order take the foreign key CustomerId
    
    // parameter resultSelector take the Customer and its matching Order
    // to make one new PackingSlip:
    (customer, order) => new PackingSlip()
    {
       Address = this.CreateAddressLines(customer),
       OrderLines = this.CreateOrderLines(order),
       TotalPrice = this.CalculateTotalPrice(order),
    });

When using LINQ it helps to use plural nouns to name collections of items, and to use singular nouns to name elements of the collections.使用 LINQ 时,有助于使用复数名词来命名项目集合,并使用单数名词来命名集合的元素。

So if you Join customers and orders (collections!), your lambda expressions should use因此,如果您加入customersorders (集合!),您的 lambda 表达式应该使用

// Get Schools, each with their Students:
schools.GroupJoin(students
school => school.Id,
student => student.SchoolId,
(school, studentsOfThisSchool) => new {...})

schools.GroupJoin(students
    x => x.Id,
    y => y.SchoolId,
   (z, a) => new {...})

You really have to look at the code to understand what is in a .你真的要看看代码来理解什么是a

Back to your question回到你的问题

Apparently you have a table with EventParticipants , where every EventParticipant has a property CustomerId .显然,您有一个带有EventParticipants的表,其中每个EventParticipant都有一个属性CustomerId You want to get only those EventParticipants that have a specific value of CustomerId .您只想获取那些具有CustomerId特定值的 EventParticipants。

int requestedCustomerId = Session["CustomerId"];
var result = dbContext.EventParticipants.
    .Where(eventParticipant => eventParticipant.CustomerId == requestedCustomerId);

Because I use plurals and singular nouns, it is easy to read: "From every eventParticipant in the table of EventParticipants, ckeck if the value of its property CustomerId equals requestedCustomerId. If so, keep the eventParticipant, if not, don't use it.因为我使用复数和单数名词,所以很容易读:“从EventParticipants表中的每个eventParticipant,检查其属性CustomerId的值是否等于requestedCustomerId。如果是,保留eventParticipant,如果不是,则不要使用它.

Now you want to count the CustomerIds that are left after your Where .现在,您要计算Where之后剩下的CustomerIds Assuming that every EventParticipant has exactly one CustomerId, you can count the EventParticipants:假设每个 EventParticipant 都只有一个 CustomerId,您可以计算 EventParticipants:

var eventParticipantCount = dbContext.EventParticipants.
    .Where(eventParticipant => eventParticipant.CustomerId == requestedCustomerId)
    .Count();

But if you really want to count the CustomerIds, you'll first to have to select them.但如果您真的想计算 CustomerIds,您首先必须选择它们。 This would be useful if you expect duplicate CustomerIds:如果您期望重复的 CustomerIds,这将很有用:

var uniqueCustomerIdCount = dbContext.EventParticipants.
    .Where(eventParticipant => eventParticipant.CustomerId == requestedCustomerId)

    // from every remaining eventParticipant select its CustomerId
    .Select(eventParticipant => eventParticipant.CustomerId)

    // remove duplicate CustomerIds:
    .Distinct()

    // and count what is left:
    .Count();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM