Kuldip Rana
Kuldip Rana

Reputation: 131

Where condition in a LINQ lambda expression

I am new to LINQ query expressions that use a lambda expression. I have one method by which I want to update the value in a different table. It is working fine in single or default, but not when I use a Where condition.

public static void UpdateData(int UserID)
{
    using (var objEntity = new DataContext())
    {

        UserMaster objUser = objEntity.UserMasters.SingleOrDefault(TBL => TBL.UserID == UserID);
        UserOfferUsed objUserUsed = objEntity.UserOfferUseds.Where(TBL => TBL.UserID == UserID);
        objUser.Purchaseon = DateTime.Now.ToString("dd MMMM  yyyy");
        objUserUsed.UsedCoupon = 0;
        objEntity.SaveChanges();
        objData = null;
    }
}

Error :Cannot implicitly convert type 'System.Linq.IQueryable' to 'Database.UserOfferUsed'. An explicit conversion exists (are you missing a cast?)

Upvotes: 1

Views: 2961

Answers (2)

Harald Coppoolse
Harald Coppoolse

Reputation: 30502

A linq statement acts on sequences that are enumerable. This means that you can say: give me the first one. and: I've got this one, give me the next one.

Most linq operators return an IEnumerable < T >, meaning, it returns another sequence. The sequence is not enumerated until you perform something like foreach or until you perform a linq statement that doesn't return en IEnumerable < T > but a T

In other words: as long as your statements return sequences the code is not really enumerated.

If you look up SingleOrDefault, you'll see that the return value is a T. To calculate the return value the sequence is enumerated.

The return value of Enumerable.Where is not a T, but IEnumerable < T >. The compiler says so.

To get the same result as your first statement you'll need the parameterless SingleOrDefault:

IEnumerable<UserOfferUsed> mySequence = objEntity.UserOfferUseds
    .Where(TBL => TBL.UserID == UserID);
UserOfferUsed objUserUsed = mySequence.SingleOrDefault();

Or if you want to do it in one statement:

UserOfferUsed objUserUsed = objEntity.UserOfferUseds
    .Where(TBL => TBL.UserID == UserID)
    .SingleOrDefault();

If you look up functions like First / Single / Any / All, Linq functions that don't return a sequence but one element of the sequence, you'll find a version with a parameter and a parameterless version. The function with the parameter has the same effect as using Where with the parameter followed by the parameterless function:

var result = SomeSequence.Last( x => SomeFunction(x))

returns the same item of the sequence as:

var result = SomeSequence.Where( x => SomeFunction(x)).Last();

Upvotes: 1

sujith karivelil
sujith karivelil

Reputation: 29036

.Where will return an IQueryable here, use .SingleOrDefault or .FirstOrDefault to get the result(if the required result is only a single item). or you can use .ToList() if the result will contains more than one element. If so you have to change objUserUsed as List<UserOfferUsed> That is, Your code will be Like this:

UserOfferUsed objUserUsed = objEntity.UserOfferUseds.FirstOrDefault(TBL => TBL.UserID == UserID);

Or Like this

List<UserOfferUsed> objUserUsed = objEntity.UserOfferUseds.Where(TBL => TBL.UserID == UserID).ToList();

You can choose one of the above according to your requirement;

Update: If the UserID is unique for each element in the list then .FirstOrDefault() will be the best option since the query will not give more than one result( you have to consider null too, Since FirstOrDefault() will give null if there is no specified match found). If you Go with the List and you want to update those values means you can do like the following:

foreach(var objUserUsed in objEntity.UserOfferUseds.Where(TBL => TBL.UserID == UserID))
{
   objUserUsed.UsedCoupon = 0;
}

Upvotes: 4

Related Questions