Strange syntax in ef - c#

var items = context.Items.Where(x => x.IsActive=true).ToList();
Why is correct syntax and working query?

This is a very subtle bug in the code. The Where Func needs to return a bool to be valid, but you are setting the value, rather than comparing it, so there's nothing to return, yes?
General Explanation
The code compiles because when you assign a value in c#, e.g. x = 1 that expression is evaluated, and therefore returned, as the value which was assigned (1).
People sometimes use this to lazily instantiate a readonly property, e.g.
private Foo myFoo;
public Foo FooInstance
{
// set myFoo to the existing instance or a new instance
// and return the result of the "myFoo ?? new Foo()" expression
get { return myFoo = myFoo ?? new Foo(); }
}
or assign the same value to multiple variables:
// set z to 1
// set y to result of "z = 1"
// set x to result of "y = z = 1"
x = y = z = 1;
Your Scenario
So what you are doing for each entry in the list is set IsActive to true and return that same true from the function. So then you end up with a new List containing all entries, and all of them have been changed to Active.
If you were using a property in the Where which is not a bool, such as an int, you would get a compilation error:
Cannot implicitly convert type 'int' to 'bool'.
See this as an example (https://dotnetfiddle.net/9S9NAV)
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var foos = new List<Foo>()
{
new Foo(true, 1),
new Foo(false, 2)
};
// works
var actives = foos.Where(x => x.IsActive=true).ToList();
// returns 2, not 1!
Console.WriteLine(actives.Count);
// compile error
var ages = foos.Where(x => x.Age = 1).ToList();
}
}
public class Foo {
public Foo(bool active, int age)
{
this.IsActive = active;
this.Age = age;
}
public bool IsActive { get; set; }
public int Age { get; set; }
}

Your example is working as your are assigning the value and not comparing value which is syntactically correct and hence it compiles and executes correctly. Note that = is used for assignment and == is used for comparison.
When you say:
var items = context.Items.Where(x => x.IsActive=true).ToList();
In this you are not comparing rather assigning the true value to IsActive which is fine for the compiler and hence you find it working.

Why it is working?
I think works because 'x.IsActive = true' will always evaluate to true. So it's not syntactically incorrect.
In other words the code is saying:
Give me all Items
Set IsActive to true for each Item
Return all Items Where(x => x.IsActive)
So as all items are set to true it will return everything.

use == for checking condition
var items = context.Items.Where(x => x.IsActive==true).ToList();
Or
var items = context.Items.Where(x => x.IsActive).ToList();

Related

Is there a way to declare a C# lambda and immediately call it?

It's possible to declare a lambda function and immediately call it:
Func<int, int> lambda = (input) => { return 1; };
int output = lambda(0);
I'm wondering if it's possible to do so in one line, e.g. something like
int output = (input) => { return 1; }(0);
which gives a compiler error "Method name expected". Casting to Func<int, int> doesn't work either:
int output = (Func<int, int>)((input) => { return 1; })(0);
gives the same error, and for reasons mentioned below I'd like to avoid having to explicitly specify the input argument type (the first int).
You're probably wondering why I want to do this, instead of just embedding the code directly, e.g. int output = 1;. The reason is as follows: I've generated a reference for a SOAP webservice with svcutil, which because of the nested elements generates extremely long class names, which I'd like to avoid having to type out. So instead of
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = CreateAddress(sh.ReceiverAddress_Shipment);
}).ToArray()
};
and a separate CreateAddress(GetOrderResultOrderShipment_OrderShipmentShipment_Address address) method (real names are even longer, and I have very limited control about the form), I'd like to write
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = sh.ReceiverAddress_Shipment == null ? null : () => {
var a = sh.ReceiverAddress_Shipment.Address;
return new Address {
Street = a.Street
...
};
}()
}).ToArray()
};
I know I could write
Address = sh.ReceiverAddress_Shipment == null ? null : new Address {
Street = sh.ReceiverAddress_Shipment.Address.Street,
...
}
but even that (the sh.ReceiverAddress_Shipment.Address part) becomes very repetitive if there are many fields. Declaring a lambda and immediately calling it would be more elegant less characters to write.
Instead of trying to cast the lambda, I propose you use a small helper function:
public static TOut Exec<TIn, TOut>(Func<TIn, TOut> func, TIn input) => func(input);
which you could then use like this: int x = Exec(myVar => myVar + 2, 0);. This reads a lot nicer to me than the alternatives suggested here.
It's ugly, but it's possible:
int output = ((Func<int, int>)(input => { return 1; }))(0);
Anonymous functions, including lambda expressions, are implicitly convertible to a delegate that matches their signature, but this syntax requires the lambda to be enclosed in parentheses.
The above can be simplified as well:
int output = ((Func<int, int>)(input => 1))(0);
Lambda literals in C# have a curious distinction in that their meaning is dependent on their type. They are essentially overloaded on their return type which is something does not exist anywhere else in C#. (Numeric literals are somewhat similar.)
The exact same lambda literal can either evaluate to an anonymous function that you can execute (i.e. a Func/Action) or an abstract representation of the operations inside of the Body, kind of like an Abstract Syntax Tree (i.e. a LINQ Expression Tree).
The latter is, for example, how LINQ to SQL, LINQ to XML, etc. work: the lambdas do not evaluate to executable code, they evaluate to LINQ Expression Trees, and the LINQ provider can then use those Expression Trees to understand what the body of the lambda is doing and generate e.g. a SQL Query from that.
In your case, there is no way for the compiler to know wheter the lambda literal is supposed to be evaluated to a Func or a LINQ Expression. That is why Johnathan Barclay's answer works: it gives a type to the lambda expression and therefore, the compiler knows that you want a Func with compiled code that executes the body of your lambda instead of an un-evaluated LINQ Expression Tree that represents the code inside the body of the lambda.
You could inline the declaration of the Func by doing
int output = (new Func<int, int>(() => { return 1; }))(0);
and immediately invoking it.
You can also create the alias in the Select method
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => {
var s = sh.ReceiverAddress_Shipment;
var a = s.Address;
return new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = s == null ?
null :
new Address {
Street = a.Street
...
}
};
}).ToArray()
};
or with the ?? operator
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order?.Select(sh => {
var s = sh.ReceiverAddress_Shipment;
var a = s.Address;
return new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = s == null ?
null :
new Address {
Street = a.Street
...
}
};
}).ToArray() ?? new Shipment[0]
};
If you don't mind violating a few of the extension methods design guidelines, extension methods combined with null-conditional operator ?. can take you reasonably far:
public static class Extensions
{
public static TOut Map<TIn, TOut>(this TIn value, Func<TIn, TOut> map)
where TIn : class
=> value == null ? default(TOut) : map(value);
public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> items)
=> items ?? Enumerable.Empty<T>();
}
will give you this:
return new Order
{
OrderDate = o.OrderDate,
Shipments = o.Shipment_Order.OrEmpty().Select(sh => new Shipment
{
ShipmentID = sh.ShipmentID,
Address = sh.ReceiverAddress_Shipment?.Address.Map(a => new Address
{
Street = a.Street
})
}).ToArray()
};
and if you mostly need arrays, then override ToArray extension method to encapsulate a few more method calls:
public static TOut[] ToArray<TIn, TOut>(this IEnumerable<TIn> items, Func<TIn, TOut> map)
=> items == null ? new TOut[0] : items.Select(map).ToArray();
resulting in:
return new Order
{
OrderDate = o.OrderDate,
Shipments = o.Shipment_Order.ToArray(sh => new Shipment
{
ShipmentID = sh.ShipmentID,
Address = sh.ReceiverAddress_Shipment?.Address.Map(a => new Address
{
Street = a.Street
})
})
};

An expression tree may not contain an out argument variable declaration

I am using c# 7.3 with new feature to create a generic method where the type should be an enum.
I have a method like this:
public static bool TryConvertToEnum<T>(this int value, out T returnedValue)
where T : struct, Enum
{
if (Enum.IsDefined(typeof(T), value))
{
returnedValue = (T)Enum.ToObject(typeof(T), value);
return true;
}
returnedValue = default;
return false;
}
It will try to convert an int to a specific enum. I am trying to use this method in two cases. One does work while the other case doesn't.
Here is the working example:
if (documentTypeId.TryConvertToEnum(out DocumentType returnedValue)
&& returnedValue == DocumentType.Folder)
{
//In this case it works fine
}
If I try to use this in a select method it does not work:
var comments = await DatabaseService.GetAll(filter)
.OrderByDescending(x => x.Id)
.ToPaginated(page)
.Select(x => new PostCommentViewModel
{
Id = x.Id,
Status = x.Status.TryConvertToEnum(out PostCommentStatusType returnedValue) ?
returnedValue : PostCommentStatusType.None //Here it does not work
}).ToListAsync();
In the second case it does not allow the project to be build. It gives the error:
An expression tree may not contain an out argument
variable declaration
When I hover, RSharper does show a popup stating: Expression tree may not contain an out argument variable declaration
I am little confused to the part may, not sure if expression tree can have or not out params...
Does anybody have any idea why this happens ?
It seemed to be an easy fix actually. I only had to materialize data before applying select function :(palmhand).
var comments = DatabaseService.GetAll(filter)
.OrderByDescending(x => x.Id)
.ToPaginated(page)
.ToList()//Applied ToList here
.Select(x => new PostCommentViewModel
{
Id = x.Id,
Comment = x.Comment,
Created = x.Created,
Name = x.Name,
ParentId = x.ParentId,
PostId = x.PostId,
Status = x.Status.TryConvertToEnum(out PostCommentStatusType returnedValue) ?
returnedValue : PostCommentStatusType.None
}).ToList();

c# list select unexpected (for me) behaviour

1. var test = new List<foo>() { new foo { prop1 ="1prop1", prop2 = "1prop2" }, new foo { prop1 = "2prop1", prop2 = "2prop2" } };
2. var test2 = test.Select(x => x.prop1 = "changed");
3. var test3 = test2.First();
Please, explain this behaviour to me.
Why foo.prop1 values change after line 3?
This is to do with deferred execution. Most linq methods defer execution until the resulting enumerable is actually enumerated. So when you run the Select statement it just creates an Enumerable that is ready to run the appropriate selector.
When you call First on the enumerable it runs the transform on the first item, thus changing its value.
This all assumes that you intended to write x.prop1 = "changed" and not x.prop1 == "changed". The former is the assignment operator which sets the value of x.prop1 and returns the set value. The latter is the equality operator and will return a boolean based on whether they are equal or not.
= is assignment, which means it actually changes values.
You want to use == instead, to check for equality.
Try:
var test2 = test.Select(x => x.prop1=="changed");
You are making an assignment = when you probably want to make an equality comparison ==.
var test2 = test.Select(x => x.prop1 == "changed");

Why does IEnumerable.ToList produce new objects

public class TestClass
{
public int Num { get; set; }
public string Name { get; set; }
}
IEnumerable<TestClass> originalEnumerable
= Enumerable.Range(1, 1).
Select(x => new TestClass() { Num = x, Name = x.ToString() });
List<TestClass> listFromEnumerable = originalEnumerable.ToList();
// false
bool test = ReferenceEquals(listFromEnumerable[0], originalEnumerable.ElementAt(0));
If I modify the copied object the original does not change.
I understand from this that System.Linq.IEnumerable<T> collections will always produce new objects even though they are reference types when calling ToList()/ToArray()? Am I missing something as other SO questions are insistent only references are copied.
Actually, the reason this is false is because your enumerable actually gets enumerated twice, once in the call originalEnumerable.ToList(), and a second time when you invoke originalEnumerable.ElementAt(0).
Since it enumerates twice, it ends up creating new objects each time it is enumerated.
You're missing the fact, that Enumerable.Range is lazy, so this line actually produce nothing but in-memory query definition:
IEnumerable<TestClass> originalEnumerable
= Enumerable.Range(1, 1).
Select(x => new TestClass() { Num = x, Name = x.ToString() });
Calling ToList() fires the query and creates list with new items:
List<TestClass> listFromEnumerable = originalEnumerable.ToList();
Calling originalEnumerable.ElementAt(0) here
bool test = ReferenceEquals(listFromEnumerable[0], originalEnumerable.ElementAt(0));
fires the query again, and produces yet another new items.
Update
So you should say, that Enumerable.Range produces new items, not ToList().
If your source collection would be already evaluated (e.g. TestClass[] array) ToList() won't create new items:
IEnumerable<TestClass> originalEnumerable
= Enumerable.Range(1, 1).
Select(x => new TestClass() { Num = x, Name = x.ToString() })
.ToArray();
List<TestClass> listFromEnumerable = originalEnumerable.ToList();
// true
bool test = ReferenceEquals(listFromEnumerable[0], originalEnumerable[0]);

LINQ query null exception when Where returns 0 rows

I have the following LINQ method that works as expected except if there are No Rows Found then I get a Null Exception. I am struggling on how I modify this to return 0 if that occurs.
public static int GetLastInvoiceNumber(int empNumber)
{
using (var context = new CmoDataContext(Settings.Default.LaCrosse_CMOConnectionString))
{
context.Log = Console.Out;
IQueryable<tblGreenSheet> tGreenSheet = context.GetTable<tblGreenSheet>();
return (tGreenSheet
.Where(gs => gs.InvoiceNumber.Substring(2, 4) == empNumber.ToString())
.DefaultIfEmpty()
.Max(gs => Convert.ToInt32(gs.InvoiceNumber.Substring(6, gs.InvoiceNumber.Length)))
);
}
}
Thanks
I tried one of Jon Skeet's suggestions, below, and now I get Unsupported overload used for query operator 'DefaultIfEmpty'
public static int GetLastInvoiceNumber(int empNumber)
{
using (var context = new CmoDataContext(Settings.Default.LaCrosse_CMOConnectionString))
{
context.Log = Console.Out;
IQueryable<tblGreenSheet> tGreenSheet = context.GetTable<tblGreenSheet>();
return tGreenSheet
.Where(gs => gs.InvoiceNumber.Substring(2, 4) == empNumber.ToString())
.Select(gs => Convert.ToInt32(gs.InvoiceNumber.Substring(6, gs.InvoiceNumber.Length)))
.DefaultIfEmpty(0)
.Max();
}
}
You're using
.Where(...)
.DefaultIfEmpty()
which means if there are no results, pretend it's a sequence with a single null result. You're then trying to use that null result in the Max call...
You can probably change it to:
return tGreenSheet.Where(gs => ...)
.Max(gs => (int?) Convert.ToInt32(...)) ?? 0;
This uses the overload finding the maximum of int? values - and it returns an int? null if there were no values. The ?? 0 then converts that null value to 0. At least, that's the LINQ to Objects behaviour... you'll have to check whether it gives the same result for you.
Of course, you don't need to use the ?? 0 if you're happy to change the method signature to return int? instead. That would give extra information, in that the caller could then tell the difference between "no data" and "some data with a maximum value of 0":
return tGreenSheet.Where(gs => ...)
.Max(gs => (int?) Convert.ToInt32(...));
Another option is to use the overload of DefaultIfEmpty() which takes a value - like this:
return tGreenSheet.Where(gs => ...)
.Select(gs => Convert.ToInt32(...))
.DefaultIfEmpty(0)
.Max();
In situations like this when there may or may not be a matching item, I prefer to return an object rather than a value type. If you return a value type, you have to have some semantics about what value means "there is nothing here." I would change it to return the last invoice, then (when it is non-null) get the invoice number from the invoice. Add a method to the class to return the numeric invoice number from the string.
public static tbleGreenSheet GetLastInvoice(int empNumber)
{
using (var context = new CmoDataContext(Settings.Default.LaCrosse_CMOConnectionString))
{
context.Log = Console.Out;
return context.GetTable<tblGreenSheet>()
.Where(gs => gs.InvoiceNumber.Substring(2, 4) == empNumber.ToString())
.OrderByDescending(gs => Convert.ToInt32(gs.InvoiceNumber.Substring(6, gs.InvoiceNumber.Length)))
.FirstOrDefault();
}
}
public class tbleGreenSheet
{
....
public int NumericInvoice
{
get { return Convert.ToInt32(InvoiceNumber.Substring(6, InvoiceNumber.Length)); }
}
...
}
Used as
var invoice = Foo.GetLastInvoice( 32 );
if (invoice != null)
{
var invoiceNumber = invoice.NumericInvoice;
...do something...
}
else
{
...do something else...
}
I had a remarkably similar experience with IQueryable<T> and NHibernate. My solution:
public static TExpr MaxOrDefault<TItem, TExpr>(this IQueryable<TItem> query,
Expression<Func<TItem, TExpr>> expression) {
return query.OrderByDescending(expression).Select(expression).FirstOrDefault();
}
The only drawback is that you are stuck with the standard default value, instead of getting to specify one.

Categories