2
\$\begingroup\$

I have been given a change to rewrite an old framework we use, and to implement the repository and unit of work patterns, but in an attempt to not rewriting all queries I have ended up with a weird combination of Linq queries and Linq lambdas.

I was hoping someone could explain to me a better way of doing this, or advice what to do.

First off, the generic repository has a method Get() defined as

public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")

and the old code would use a context directly like this:

Arrival arrival =
    (from a in DataContextPortX.Arrival
         where a.I_ARRIVALNO == arrivalNo
     select a).SingleOrDefault();

And now, since the class no longer has direct access to the context I can choose to keep the old code with the Get() method mixed in like this:

Arrival arrival =
    (from a in Get()
        where a.I_ARRIVALNO == arrivalNo
        select a).SingleOrDefault();

or I can rewrite the whole query to lambda like this:

var arrival = Get(a => a.I_ARRIVALNO == arrivalNo).SingleOrDefault();

I would of course prefer to rewrite all queries but there are a lot of them, and this was the shortest I could find, others are like really long.

But I am worried about first using Get() and then iterating of that, but for all I know it doesn't matter.

\$\endgroup\$
1
  • \$\begingroup\$ What you do will depend largely on whether Get() defers execution. If it forces execution prior to return, you may want to pass the filter expression so it is included as part of the executed SQL statement. \$\endgroup\$
    – Dan Lyons
    Commented May 15, 2014 at 17:28

2 Answers 2

2
\$\begingroup\$

There is a reason why you can write LINQ queries using the query syntax or the method syntax: sometimes one is better and sometimes it's the other one.

So, when you're writing a new query, use the syntax that suits your query better. This usually means method syntax for simpler queries (especially if they're as simple as your example) and query syntax for more complicated queries (especially ones with multiple sources).

When you need to use an operator that's only available in method syntax (like SingleOrDefault()), I think that points towards using method syntax for the whole query. But using both syntaxes in the same query can sometimes make sense too.

When it comes to rewriting old code: if it works and it's reasonably readable, I would leave it be, I think the effort spent rewriting it isn't worth it.

\$\endgroup\$
4
  • \$\begingroup\$ I agree with "leave it be" if it works/readable. I strongly disagree that using SingleOrDefault implies the entire query should be method syntax. Single/ToList/First*Default are dependent on what the query is intended to return. Whether you built that query using LINQ or extension methods doesn't matter, either way it is how you are executing the query and going from IQueryable to IEnumerable. \$\endgroup\$
    – AaronLS
    Commented May 15, 2014 at 17:07
  • \$\begingroup\$ @AaronLS Adding a method like Single() at the end of a query syntax means it's slightly ugly, because you need to enclose it in parentheses. So, when making the decision between the two syntaxes, to me this adds a point towards using method syntax. But that single point may not tip the scales, so query syntax for most of the query may still be the better option. \$\endgroup\$
    – svick
    Commented May 15, 2014 at 17:11
  • \$\begingroup\$ That's no different than ToList, as you have to enclose it in parenthesis as well. In both cases you have two choices, delay execution by returning an IQueryable or execute immedietely var someQuery = from...select a; someQuery.ToList() or (from...select a).ToList(), as with Single var someQuery = from...select a; someQuery.Single() or (from...select a).Single() \$\endgroup\$
    – AaronLS
    Commented May 15, 2014 at 18:11
  • \$\begingroup\$ Point being, at some point you have no choice but to introduce one final extension method that processes the IQueryable into an actual result, so that shouldn't be a factor in the decision making process. \$\endgroup\$
    – AaronLS
    Commented May 15, 2014 at 18:17
0
\$\begingroup\$

It's really up to you which style you want to do.

On a side note, I wouldn't do this:

Arrival arrival =
    (from a in Get()
        where a.I_ARRIVALNO == arrivalNo
        select a).SingleOrDefault();

Mainly because the purpose of that Get() function is to accept an Expression so it can build an SQL query with the parameters that will be sent to the database. What the above code is doing, is a "Get All, then filter" rather than "Get filtered data". You want the latter.

Anyways, as for the query style - it doesn't matter what style you use, as long as your code is readable/clear. Sometimes query format is just easier - e.g. I hate lambda Join() - i can never remember the syntax for it, so I always write it in query syntax. It just makes more sense to me. Where as other query types like Single(), Where(), First() are just easier/quicker as lambdas.

Remember, you can mix query styles:

var query = from a in Whatever ....

if (something == false)
    query = query.Where(w => w.YouGetTheIdea);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.