Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq to SQL - what's better?

db.Albums.FirstOrDefault(x => x.OrderId == orderId)

or

db.Albums.FirstOrDefault(x => x.OrderId.Equals(orderId))
like image 811
Sasha Avatar asked May 13 '10 10:05

Sasha


2 Answers

I'm going to try to convince you that:

  • The two methods you proposed give the same performance.
  • There are at least two non-performance related reasons you should prefer ==.
  • There is another separate improvement that you can make to your code to reduce the possibility of errors.

To see that the performance will be the same, look at the SQL generated in each case. This test program shows you how you can view the generated SQL:

int orderId = 4;
TextWriter textWriter = new StringWriter();
using (var dc = new DataClasses1DataContext())
{
    dc.Log = textWriter;
    Order o1 = dc.Orders.FirstOrDefault(x => x.OrderId == orderId);
    Order o2 = dc.Orders.FirstOrDefault(x => x.OrderId.Equals(orderId));
}
string log = textWriter.ToString();

The SQL sent in each case is the same, as you can see by inspecting the log:

SELECT TOP (1) [t0].[OrderId], [t0].[CustomerID], [t0].[Date], [t0].[Description]
FROM [dbo].[Order] AS [t0]
WHERE [t0].[OrderId] = @p0

SELECT TOP (1) [t0].[OrderId], [t0].[CustomerID], [t0].[Date], [t0].[Description]
FROM [dbo].[Order] AS [t0]
WHERE [t0].[OrderId] = @p0

Regarding whether to use == or Equals, firstly I'd suggest using == for readability. This is the idiomatic way to compare two integers in C#.

Secondly with == you will get a compile time error if you give objects of different (incompatible) types. I assume that in your case order has type int, but let's assume that someone else wrote this code and accidentally made an error where order is a variable of type Order instead of an int. Now let's compare what would happen in each case:

Order order = new Order { OrderId = 4 };

x.OrderId.Equals(order)  // This compiles, but you get an exception at runtime:
                         // Could not format node 'Value' for execution as SQL.

x.OrderId == order       // Compile error: Operator '==' cannot be applied to
                         // operands of type 'int' and 'Order'

It is better to get compile time errors than runtime errors, so prefer to use == in this case.

Finally, if you only expect one result you should prefer to use SingleOrDefault instead of FirstOrDefault as the former will throw an exception if there are two matching objects found instead of just returning the first. This extra check will cost a tiny amount in performance but again allows you to catch errors earlier. If performance is a critical issue for you, instead of removing these safety checks you should consider fetching multiple objects from the database at once, not one object at a time.

So in summary I recommend that you use this:

Album album = db.Albums.SingleOrDefault(x => x.OrderId == orderId);
like image 110
Mark Byers Avatar answered Sep 28 '22 23:09

Mark Byers


They will both be equivalent from a performance perspective. I tend to prefer == over .Equals() for readability, but the beauty of L2S is that you can use either one, depending on what type of object you have.

(And I'm assuming your second statement is on the orderId, and not the order object)

like image 22
Dave Markle Avatar answered Sep 29 '22 00:09

Dave Markle