How eagerload Multilevel hierarchy with Simple.Data? - c#

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".

Related

Automapper , Linq and Localizaton

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?"

Dynamics CRM 2011 - Getting set of N:1 related entities with QueryExpression

I'm working on a custom web service for a CRM 2011 deployment, and I'm now making an overview which relates to some of our entities. We have a custom product entity with details such as the product name and category, and we have an agreement entity, which links the product to the customer and contains product details specific to that customer. agreement and product have an N:1 relationship.
I'm now making an overview page that will be displayed on the customer page in CRM, which should display all agreements on that customer. For this display, I also need to retrieve some information about the products these agreements link to, which will be used to group the agreements on the overview page. I've been unable to find any relevant/specific examples on this, and I'm stuck trying to find a feasible way of querying for the data I need.
The way I imagine it, I would like to use two queries to get the required data. First, a query that gets all the agreements on the customer. Then pass this list to a second query, which returns all the products that intersect the first list. Is this possible using a QueryExpression, or do I need to loop over the agreement list and run a separate query for each individual association? I'd prefer to avoid FetchXML if possible.
If I understand your question right, you'll just need to add a LinkEntity to your Product entity on the first query. You can also specify attributes of the Product entity to return as well, but they get returned as AliasedValues, so be aware of that.
Adding to Daryls answer, you can see this post for an example on how to link entities. MSDN is confusing on the subject (at least to me).
I'm proposing a nice structure of query expression there, while Daryl presents a more compact equivalent. (Mine is of course better. :D )
I looked at LinkEntity, but I eventually achieved what I wanted to do with ConditionOperator.In on the second query, like this:
query.Criteria.AddCondition(
new ConditionExpression(
"myprefix_productid",
ConditionOperator.In,
agreementList )
);
Where agreementList is an array of Guids. I tried this before posting the question as well, but without wrapping the parameters in new ConditionExpression(), which didn't work. Presumably this was because the implicit way invoked the wrong overload for the AddCondition function.
Useful links in the other answers though, I'll look into them as well!

DataLoadOptions equivalent for LINQ to Entities?

Is there a version of the DataLoadOptions class that exists in LINQ to SQL for LINQ to Entities? Basically I want to have one place that stores all of the eager loading configuration and not have to add .Include() calls to all of my LINQ to Entities queries. Or if someone has a better solution definitely open to that as well.
TIA,
Benjy
Personally I'm glad that there is no (official) EF equivalent of DataLoadOptions. Why? A few reasons:
It is too easy to use them in a way that exceptions are thrown, see the remarks section of the MSDN page.
I don't like the concept of filtered child collections. When a Customer has Orders, I want the Orders member to represent the orders of that customer (lazy or not). A filter defined somewhere else (by AssociateWith) is easily forgotten. I will filter them when and where needed. This leads to the last objection:
Most importantly: it is stateful and most bugs are caused by unexpected state. DataLoadOptions change the DataContext's state in a way that later queries are influenced. I prefer to define eager loading where and when I need it. Typing is cheap, bugs are expensive.
Nevertheless, for completeness's sake I should mention that Muhammad Mosa did put some effort in an EF version of DataLoadOptions. I never tried it though.
I realize that you probably want to prevent repetitive code. But if you need identically shaped queries in more than one place you are already repeating code, with or without "globally" defined includes. A central eager loading configuration is pseudo DRY-ness. And soon you'll find yourself tripping over your own feet when eager loading is not desired but, darn, it's configured to happen!
Entity Framework does not support eager loading settings for the whole 'ObjectContext'. But you can declare all required 'IQueryable' properties with include options in a partial class. For example:
public IQueryable<Order> Orders {
get {
return OrderSet.Include("OrderDetails");
}
}

How to efficiently delete all but the latest x children of parent entity using NHibernate?

Please forgive me if I don't explain this very well. First off, I am using NHibernate 2.0 with .NET 3.5. Basically I have an entity "EntityA" (for simplicity) with one or more children of type EntityB. Each EntityB has a number indicating how recently it was created. I would like to delete all but the x most recent EntityB. This forms part of a purge operation.
I am struggling to see an efficient way of doing this, The problem is that the EntityB instances are actually quite complex and could have hundreds of child objects themselves. The list of EntityB on EntityA is lazily loaded and I would ideally like to avoid loading it in memory if possible.
I tried passing an HQL query to Session.Delete. Unfortunately HQL doesn't seem to support the top statement so I cannot do a subselect to choose which ones not to delete.
The cascades are set up in NHibernate and not in the database. I'm not sure but I wonder if NHibernate will load the whole object graph even if the delete is done via HQL.
Any advice would be appreciated.
[Edit]Unfortunately any query must be HQL not SQL since it needs to be database independent[/Edit]
Cheers,
James
From my experience with nHibernate I don't think you're going to find a clean solution for this. But, it doesn't matter. Stepping outside the framework is only a bad thing if the framework offers a viable alternative. Use a parameterized SQL statement, make sure it's clear in the code where and why you're doing this and it'll be a great solution.
EDIT:
I'm fairly certain you could come up with a database independent SQL query for this but anyway... Instead of trying to use a top statement try using MAX() (assuming there is such a function in HQL) to grab the top item id and then structure a delete statement with a conditional that the id is not the MAX id.
You should be able to use HQL delete Child c where c in (:list) where list is a copy of the list of children with only the to-be-removed elements included. list may be obtained through an HQL query such as from Child c where c.Parent = :parent - HQL queries apparently do not obey the mapping's fetch strategy (lazy vs eager) and will only fetch children eagerly when instructed to fetch children eagerly (so just don't put in the left join fetch c.SubChildren) - and then filtered to include only the elments to be removed.
If nothing else you could set up the cascades in the database and just do
Session.CreateSQLQuery([SqlStatement]).SetParameter([ParameterStuff]).ExecuteUpdate();
I always try to keep cascades, default values, etc set up in both the database and nhibernate for cases like this when you need to do something directly to the database.

Why won't entity framework allow me to do a .FindBy....()

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.

Categories

Resources