Linq2DB arbitrary Where clause - linq2db

I'd like to be able to implement a search method that can take any arbitrary properties of my POCO class as arguments. This works well:
public static IEnumerable<iUser> Search(DataContext context, Func<iUser, bool> predicate)
{
return from i in context.GetTable<iUser>().Where(predicate) select i;
}
but in this case the filtering appears to take place after collecting all the rows in the table.
Is it possible to use Linq to generate an arbitrary query like this without filtering after the sql call? What approaches would you recommend?
Thanks!

LINQ to DB is an Object-Relational Mapper (ORM) that is capable of translating LINQ expressions into SQL. The word "expression" is important here. A Func is not an expression but a delegate, you have to use Expression<Func<>> in LINQ methods for LINQ to DB to be able to translate them. Otherwise the data will be pulled from the database first after which the Func filters them in memory.
So your function should look like:
public static IEnumerable<iUser> Search(DataContext context,
Expression<Func<iUser, bool>> predicate)
{
return context.GetTable<iUser>().Where(predicate);
}
The return type depends on the what you want the caller of this function to be capable of. If you return IQueryable<iUser> the caller will be able to extend the expression by their own expressions. That is, Search(context, somePredicate).Where(...) will be translated into SQL as a whole. Returning IEnumerable will apply any subsequent predicates (either as Func or as Expression) in memory.
Side note, in order to line up with common naming conventions, if iUser is an interface (I have no idea if LINQ to DB supports interfaces) then you should rename it into IUser, otherwise name it User.

Related

IEnumerable vs IQueryable in OData and Repository Pattern

I watched this video and read this blog post. There is something in this post confused me; The last part of the post. In the last part Mosh emphasized, Repository should never return IQueryable, because it results in performance issue. But I read something that sounds contradictory.
This is the confusing part:
IEnumerable: While querying data from database, IEnumerable executes select query on server side, load data in-memory on client side and then filter data. Hence does more work and becomes slow.
IQueryable: While querying data from database, IQueryable executes select query on server side with all filters. Hence does less work and becomes fast.
this is another answer about IQueryable vs IEnumerable in Repository pattern.
These are opposite of Mosh's advice. If these are true, why we should not use IQueryable instead of IEnumerable.
And something else, What about situations that we want to use OData; As you know it’s better to use IQueryable instead of IEnumerable when querying by OData.
one more thing, is it good or bad to use OData for querying e-Commerce website APIs.
please let me know your opinion.
Thank you
A repository should never return a IQueryable. But not due to performance. It's due to complexity. A repository is about reducing the complexity in the business layer.
Buy exposing an IQueryable you increase the complexity in two ways:
You leak persistence knowledge to the business domain. There is things that you must know about the underlying Linq to Sql provider to write effective queries.
You must design the business entities so that querying them is possible (i.e. not pure business entities).
Examples:
var blockedUsers = _repository.GetBlockedUsers();
//vs
var blockUsers = _dbContext.Users.Where(x => x.State == 1);
var user = _repos.GetById(1);
//and an enum is used internally in the user class
user.Block();
_repos.Update(user);
// vs
var user = _dbContext.Users.FirstOrDefault(x => x.Id == 1);
user.State = 1;
_dbContext.SaveChanges();
By wrapping everything behind your repository, you design your business entities in a way that make it easy to work with them (child entites, enums, date management etc). And you design the repository so that those entities can be stored in an efficient way. No compromises and code that is more easily maintained.
Regarding OData: Do not use the repository pattern. It doesn't add any value in that case.
If you insist on using IQueryable in your business domain, do not use the repository pattern. It would only complicate things without adding any value.
Finally:
Business logic that uses properly designed repositories is so much easier to test (unit tests). Code where LINQ and business logic is mixed must ALWAYS be integration tests (against a DB) since Linq to Sql differs from Linq to Objects.

Does it matter what Domain Object you execute a query on in grails

Does it matter what domain object you use when you execute a query? For instance, I have these two domain objects
Class A {
String name
}
Class B {
String name
}
If I want to get all A objects, I can do the following
A.executeQuery('FROM A')
But I can also call the same query from a different domain object and get the exact same results as so
B.executeQuery('FROM A')
Is there a difference between these two statements performance wise? Maybe something under the hood that is happening differently?
For a little more context, I am writing a service where the application will be executing queries off of domain objects dynamically. So I could either pick a base domain object and just execute off that every time, or I can maybe make an instance of the domain object with a string that is provided into the method.
Thanks
No, it does not matter. In this case it's just executing HQL (hibernate query) and either domain class acts exactly the same in this respect for executeQuery.
In your specific case I'd just use a single domain class to execute all the queries from. No need to change the type.
Does it matter what domain object you use when you execute a query?
It depends on what query technique you are using. For executeQuery in particular it does not. For most other query techniques it does. For example, A.executeQuery('FROM A') is the same as B.executeQuery('FROM A'). A.list() is not the same as B.list(). A.findAllByTitle('Tribe') is not the same as B.findAllByTitle('Tribe'), A.where { ... } is not the same as B.where { ...}, etc...

Proper implementation of Repository Pattern using IQueryables?

I'm building a Repository layer for my MVC application with methods like GetObject, UpdateObject, DeleteObject, etc.
This is what I have now:
public List<Object> GetObjects()
{
return _db.Objects.Where(o => o.IsArchived == false).ToList();
}
But I'm wondering if it would be better to return IQueryables for lists so that the least amount of data gets sent to the client when filters are applied in the UoW or Service layers. Would it be best to do something like this?
public IQueryable<Object> GetObjects()
{
return _db.Objects.Where(o => o.IsArchived == false);
}
The not nice thing about returning IQueryable, is that if you ever have a different implementation of repository, say using different ORM, storing data in non-SQL database, cloud or XML file, it would be hard to implement same interface. It would be much easier to implement if you return more generic colections of domain objects. For example IEnumerable. You can always pass filtering criteria in.
The other drawback of returning IQueryable, is that it may happen, that when you actually run the query your object context may be already disposed (Depending on your implementation) or may be kept in memory longer than required.
A leaky abstraction such as IQueryable could cause problems, for example imagine you want to get some data from database and order it by Guid. If you enumerate the query by calling ToList() prior to sorting, you'll get different results if you do it after. The reason is that in first case the sorting will happen in .NET, but in other case it will happen in SQL which uses completely different order.
The nice thing about returning IQueryable here is that you can continue to build up your query further without hitting the db. Once you call ToList it will hit the db and you can't customize your query further without hitting the database a second time.

Should a LINQ projection be strongly typed

I have an aggregated data view in an MVC project which displays the totals per month broken down by audit status. The controller code sets this up using a simple LINQ projection into an anonymous object like this:
From audits In db.Audits
Group By key = audits.DateCreated.Value.Month Into g = Group
Select New With {
.Month = key,
.Assigned = g.Sum(AuditsWithStatus(AuditStatus.Issued)),
.Unassigned = g.Sum(AuditsWithStatus(AuditStatus.Pending)),
.Closed = g.Sum(AuditsWithStatus(AuditStatus.Closed)),
.Cancelled = g.Sum(AuditsWithStatus(AuditStatus.Cancelled))
}
I know this is one of the big advantages of LINQ (using anonymous types), but I don't like losing the strong typing in the view (ie #ModelType SomeStrongType). Is there any general advice on this? Articles, blogs, or other places that deal with the issue and when to use which?
You cannot do anything with anonymous types outside of the scope of your method. You cannot return them to your view for example. In those cases you have to use a known type.
I use anonymous types when I am selecting data that I am then processing in another way. For example, selecting some bespoke data out of 1 source using Linq, and putting to put into another source.
If you are returning aggregate data such as an IEnumerable<IGrouping<TKey, TValue>> and TKey and TValue are anonymous types (you can group by anonymous types if you want); then you would not want to create 2 classes for TKey and TValue, where TKey has an overridden Equals and GetHashCode so you can group by it. And then do nothing more than read some values from it and throw it away, never to be re-used.
TLDR; use them when there is no need to create a known type to store your results. If you need to pass your results to somewhere outside the scope of the method, then you will need a type.
General advice is simple: always create dedicated viewmodel type for your views. In your case it would be pretty simple, containing exactly the properties you have in you anonymous class.
I understand that it seems like an unneeded overhead, but it'll make your code more readable and verifiable.

Can you map the results of a manual SQL query to objects in Entity Framework?

In LINQ, you can write a manual SQL query, take the results from it and have LINQ "map" those into the appropriate properties of your Model classes (or at least, I'm pretty sure I read you can do that).
Is it possible to do something like that in Entity Framework?
I have an web app that's using EF, and it's CPU usage is ridiculously high compared to the traffic it has, and profiling it in my machine, all that time is (predictably) spent in the DB functions, and the largest portion of that time (> 85%) is spent by EF "generating" SQL and doing stuff before actually executing a query.
So my reasoning is that I can just go in and hardcode the SQL queries, but still use my populated Model properties in my view.
Is this possible? If so, how would I do it?
Thanks!
Daniel
So what you want to do is hydrate an object from an IDataReader? It's pretty easy to write code to do this (hint: reflection! or you can get fancy and use a member initialization expression) or you can Google for myriad existing implementations on the Internet.
You can do this within EF using ObjectContext.ExecuteStoreQuery<T> or ObjectContext.Translate<T> if you already have a DbDataReader.
1 ObjectContext.SqlQuery in EF 4.0
As said #Jason, you can :
IEnumerable<MiniClient> results =
myContext.SqlQuery<MiniClient>("select name,company from client");
Reference : https://msdn.microsoft.com/en-us/library/dd487208.aspx
DbContext.Database.SqlQuery, in EF 4.1+
In Entity Framework 4.1+, DbContext is preferable to use to ObjectContext, so you'd better use :
DbContext myContext= new DbContext();
IEnumerable<MiniClient> results =
myContext.SqlQuery<MiniClient>("select name,company from client");
Reference : https://msdn.microsoft.com/en-us/library/jj592907(v=vs.113).aspx
dynamic and anonymous class
Too lazy to create a projection class like MiniClient ?
So you should use anonymous type and dynamic keyword :
IEnumerable<dynamic> results =
myContext.Clients.Select( c => new {Name = c.Name, Firstname = c.Firstname});
Note : In all the samples MiniClient is not an entity of the DbContext.
(=not a DbSet<T> property)

Resources