I create a EDM using my database and saw that while it was able to make relations like
Customers.First().Orders
there is nothing like
Customer.First().Orders.FindOrderByOrderID()
Customer.First().Orders.FindOrderByOrderName()
etc.
Maybe I was expecting it to be like that and that's how it doesnt work
and I will probably just have to LINQ to entities and create mangers that handle business logic in them.
or does LINQ to SQL do this?
You can use LINQ with the Orders property, like this:
var order = Customer.First().Orders.FirstOrDefault(o => o.OrderId == someId);
This will return null if there was no matching Order.
With LINQ to Entities you can do this. Such as the example SLaks posted above.
If you're feeling adventurous, it is possible to write a function to do this. Since Entity Framework knows which column is the primary key it is possible to write a function like GetEntityByPrimaryKey.
CodeProject has an article regarding the repository pattern and if you search for "SelectByKey" you'll see their implementation of that. I use something similar and find it very helpful.
The idea is that you can use LINQ to write more flexible queries. Note, however, that you could probably so something like FindOrderByOrderName in .NET 4.0 by creating your own dynamic type (not trivial), that responded to calls following this pattern by building a LINQ query automatically. You'd lose intellisense, of course, and I doubt it would be worth it, but it could be done.
Related
I am getting this error while using this IEquality comparer for intersection.
Can somebody identify where I am doing it wrong?
Pleas ask if you need more information.
When you write LINQ to Entities, you must remember that eventually all of your LINQ expression is translated to SQL. So for every method call you make in that expression, you should think if there's a reasonable way to translate it to SQL.
Having that in mind, you can see that:
SQL has no notion of .ToList(), which is probably the source of your current error. calls to .ToList() should be made at the end of the expression, as a way to "materialize" the query (i.e. make EF make the actual call to the database and return results).
Your database knows nothing about C# interfaces. You can't expect any implementation of IEqualityComparer to be translatable to SQL.
As #Dai has noted, you seem to be using too many joins. Make sure your model has the right navigation properties between entities, and use them.
Recently I have been playing with AutoMapper as a tool to populate our DTOs.
The cool thing about AutoMapper is its Project().To() that let us map a Queryable so that we can select the fields that we want according to our map.
But here we have another scenario too.We want to be able to translate some of the values of an entity into other representation.
Suppose that we have a string field that its value in DB is 'Apparatment' and we want to translate it to another language while we are selecting our DTOs.
I think that if we want to write this in SQL it will be something like this :
SELECT CASE BuidlingType WHEN 'Appartment' THEN 'apparatment in another langaure' WHEN 'Flat' THEN 'flat in another languate' END AS BuildingType FROM buildings
I know that we can define value resolvers in AutoMapper. The question I would like to ask is ,can we use these resolvers in a Project().To() scenario ? If the answer is yes then how we should use them (to return an expression instead of a value) and if not , is there any other alternative approach to be able to translate a DTO on the fly ?
No you can't use resolvers in LINQ projections.
I guess I'm a little confused - those translations look a little difficult in the SQL you have. Are your translations stored in a database, or do you hard code them in your SQL?
Typically my localized labels are stored either in resource files or specialized tables. If they're in tables, I don't necessarily returned translated data labels with data. I have two queries and the translation query is almost certainly cached.
I would start with "What LINQ do I build to make the correct SQL" and then I can help with "how can I configure AutoMapper to build this LINQ?"
I was wondering if it was possible to select/build a multilevel object hierarchy in one single query? As I'm not sure about the terminology, I'll give an example:
Let's say we have a Product, which has one Subrange, which has one Range, which has one Provider.
I can easily build my Product POCO with its Subrange with
Db.Products.WithSubrange.Get(#id);
But could I build it with Product.Subrange.Range and Product.Subrange.Range.Provider in a single query?
I've tried several ways, like:
Db.Products.With(Db.Products.Subrange.WithRange()).Get(#id);
Db.Products.With(Db.Subrange.WithRange()).Get(#id);
but I can't find it out. It would be ok to query the Range and Provider afterward (it's already amazing this way) but a single query would be nice. Explicit Joins maybe?
BTW if Sir Rendle happens to come-by, I would like to thank him for his amazing work. Simple.Data rocks!
Try chaining the 'With's
Db.Products.WithSubRange().WithRange().WithProvider().Get(#id);
Alternatively you can use
Db.Products.FindAllById(#id).WithSubRange().WithRange().WithProvider().FirstOrDefault();
Read: http://simplefx.org/simpledata/docs/pages/Retrieve/LazyVsEagerLoading.htm
The act of doing what you have described relates to the terms "Lazy Loading" and "Eager Loading".
Is there a way to use Linq-to-SQL with nhibernate envers to query through revisions without having to use envers audit expressions?
I would like to avoid using something like this, which requires hardcoded string property names:
reader.CreateQuery()
.ForEntitiesAtRevision(1)
.Add(AuditEntity.Property("FirstName").Eq("bob"))
.Results();
No. The only built in query api is the "criteria like" you mention.
I have been puzzling over a problem this morning with LinqToSQL. I'll try and summarise with the abbreviated example below to explain my point.
I have DB two tables:
table Parent
{
ParentId
}
table Child
{
ChildId
ParentId [FK]
Name
Age
}
These have LinqToSQL equivalent classes in my project, however, I have written two custom model classes that I want my UI to use, instead of using the LinqToSQL classes.
My data access from the front end goes through a service class, which in turn calls a repository class, which queries the data via linq.
At the repository level I return an IQueryable by:
return from data in _data.Children
select new CustomModel.Child
{
ChildId = data.ChildId,
ParentId = date.ParentId
};
My service layer then adds an additional query restriction by parent before returning the list of children for that parent.
return _repository.GetAllChildren().Where(c => c.Parent.ParentId == parentId).ToList();
So at this point, I get the method has no supported translation to sql error when I run everything as the c.Parent property of my custom model cannot be converted. [The c.Parent property is an object reference to the linked parent model class.]
That all makes sense so my question is this:
Can you provide the querying process
with some rules that will convert a
predicate expression into the correct
piece of SQL to run at the database
and therefore not trigger an error?
I haven't done much work with linq up to now so forgive my lack of experience if I haven't explained this well enough.
Also, for those commenting on my choice of architecture, I have changed it to get around this problem and I am just playing around with ideas at this stage. I'd like to know if there is an answer for future reference.
Many thanks if anyone can help.
Firstly, it begs the question: why is the repository returning the UI types? If the repo returned the database types, this wouldn't be an issue. Consider refactoring so that the repo deals only with the data model, and the UI does the translation at the end (after any composition).
If you mean "and have it translate down to the database" - then basically, no. Composable queries can only use types defined in the LINQ-to-SQL model, and a handful of supported standard functions. Something similar came up recently on a related question, see here.
For some scenarios (unusual logic, but using the typed defined in the LINQ-to-SQL model), you can use UDFs at the database, and write the logic yourself (in TSQL) - but only with LINQ-to-SQL (not EF).
If the volume isn't high, you can use LINQ-to-Objects for the last bit. Just add an .AsEnumerable() before the affected Where - this will do this bit of logic back in managed .NET code (but the predicate won't be used in the database query):
return _repository.GetAllChildren().AsEnumerable()
.Where(c => c.Parent.ParentId == parentId).ToList();