Dynamic Data Querying using Entity Framework (EF) - entity-framework

I would like to hear some feedback on a scenario that I am trying to implement. I have currently implemented this scenario using Criteria API for NHibernate and was wondering if there was anything similar that was implemented for Entity Framework 4.1.
I have a need where the end user can select filtering criteria from the UI and thus build a query that can contain complex AND/OR criteria.
For e.g.: The user can say: I want Students with (Zip Code = 92037 AND Gender = F) OR (ZipCode = 92101 and Gender = M)
OR
I want students with (State = CA OR State = FL) AND GPA = 4.0 AND GENDER = M
These queries are usually built using a tree control on the front end.
I currently have this working using NHibernate. The Criteria API in NHibernate is really awesome for doing this. However, NHibernate has a major bug, and that is it doesn't allow multiple joins on a 1:many table.
So for e.g. if I had a table containing a CATCODE (Category code) and an Answer, NHibernate will not currently let me do multiple querying using Criteria API.
So I cannot for e.g. do: WHERE CATCODE = A and Answer in (A,B,C) AND CATCODE = B and Answer in (V,H,Y).
Due to this limitation, I have been trying to move out of NHibernate into Entity Framework. I didn't know if there was a nice way to do this kind of stuff using APIs.
Can anyone tell me a better solution to achieve such functionality, if there is one?
Would love to hear from both NHibernate and EF experts if there are ways to solve this.

I don't really know NHibernate or any other OR/M except the entity framework but let assume you have an entity called Category, and category have relation to Answers (each category has many answers for example).
So the Category entity looks like:
public class Category {
public virtual string CATCODE{get;set}
public virtual IList<Answer> Answers{get;set;}
}
And then you can do something like:
Categories.Where(x=>x.CATCODE =="A").Where(x=>x.Answers.Any(l=>l.Name=="1" || l.Name=="2" || l.Name==3)
I even sure there is a better way to write this query, but the point is that it is possible.

Related

How to use Entity Framework with a database without relationships defined

I am new to EF so please bear with me. I am using Entity Framework with an existing database in which the relationships are not defined.
Using EF, I am able to produce the model, but obviously the 'navigational properties' are not working. Is there a way I can specify the mapping between the entities?
For example, in my Product entity, I have a field CategoryID_fk (maps to Category entity). But since the relationships are not defined, I cannot load a Category while loading a Product entity.
Can someone guide me in this regard?
I do understand that it would be preferable to refactor our database but I am unable to do that now. Thanks in advance.
This link is very useful.http://www.entityframeworktutorial.net/
I think field names are not suitable conventions.Try to change field name as CategoryId or Category_CategoryId .I think it will work
Yes, you can do a group join. Basically you will retrieve Products and Category in separate queries and take an approach as indicated in this answer.
Something along these lines:
var productCategoryList = products.GroupJoin
(
categories,
p=> p.productId,
c=> c.CategoryId,
(p, c) => new ProductCategory
{
//Create your Product Category model here
}
).AsEnumerable();

E-SQL in Entity Framework DbContext

I'm using EF 5.0 Code First API, and I need to add the ability for building dynamic OrderBy expressions (the UI has a filter panel where users can choose multiple oredering criteria (e. g. select top 20 Customers, order by LastName ASC, then by Birst Date DESC).
ObjectContext API exposes OrderBy("it.PropertyName") method which looks great, despite it's missing compile time verification. However, I can't find any analogues in the DbContext API.
Googling the problem I found such advice:
((IObjectContextAdapter)myContextInstance).ObjectContext.CreateQuery<MyEntity>("<ESQL Query>")
However, I would not like to give up LINQ query at all.
Are there any ways to have something like this (mix ESQL and LINQ, as it could be by using ObjectContext):
var customers = myDbContext.Customers.OrderBy("it.LastName desc").Where(c => c.Age < 18)
Something like this? I'm not sure about mixing ESQL and LINQ, but your last query can be done entirely from LINQ.
var customers = myDbContext.Customers.OrderByDescending(a => a.LastName).ThenBy(c => c.BirthDate).Where(b => b.Age < 18);

Wide and narrow versions of an entity mapped to one table in Entity Framework

In some scenarios I need a "wide" version of an entity with many properties (say FullCustomer) while in other scenarios it's enough with a "narrow" version with few properties (say MiniCustomer), how could I map these two entities, FullCustomer and MiniCustomer, to the same Customer table in the database? Furthermore, I need to be able to query and update both entities.
Thanks in advance for any advice or pointers!
PD. I'm using VS2010 RC and EF 4
For "efficiency", don't have two versions of the entity; just project onto "lite" POCOs:
var q = from e in Context.Entities
select new LitePoco
{
Id = e.Id,
EditThis = e.EditThis
};
No other columns will be returned.
Similarly for save:
var e = new MyEntity { Id = 123 };
Context.AttachTo("Entities", e);
// anything from here on gets saved
e.EditThis = "Edited";
Context.SaveChanges();
If you have a column that determines whether to treat the record as a FullCustomer or as MiniCustomer, then you can easily create a Table per Hierarchy inheritance model with FullCustomer inherited from MiniCustomer. Such approach is described in the Muhammad Mosa's blog post.
If you don't have this column you can update the model and database in order to add it.
However, there is an alternative approach. If the reason to have two entities for one table is the delay in the loading the numerous large properties in the FullCustomer object, than Table Splitting might be an option. Take a look at the Julie Lerman's blog post.
I would have noted that this problem is not present in ORMs like LINQ to SQL, due to deferred loading.

How to sort related entities with eager loading in ADO.NET Entity Framework

Greetings,
Considering the Northwind sample tables Customers, Orders, and OrderDetails I would like to eager load the related entities corresponding to the tables mentioned above and yet I need ot order the child entities on the database before fetching entities.
Basic case:
var someQueryable = from customer in northwindContext.Customers.Include("Orders.OrderDetails")
select customer;
but I also need to sort Orders and OrderDetails on the database side (before fetching those entities into memory) with respect to some random column on those tables. Is it possible without some projection, like it is in T-SQL? It doesn't matter whether the solution uses e-SQL or LINQ to Entities. I searched the web but I wasn't satisfied with the answers I found since they mainly involve projecting data to some anonymous type and then re-query that anonymous type to get the child entities in the order you like. Also using CreateSourceQuery() doesn't seem to be an option for me since I need to get the data as it is on the database side, with eager loading but just by ordering child entities. That is I want to do the "ORDER BY" before executing any query and then fetch the entities in the order I'd like. Thanks in advance for any guidance. As a personal note, please excuse the direct language since I am kinda pissed at Microsoft for releasing the EF in such an immature shape even compared to Linq to SQL (which they seem to be getting away slowly). I hope this EF thingie will get much better and without significant bugs in the release version of .NET FX 4.0.
Actually I have Tip that addresses exactly this issue.
Sorting of related entities is not 'supported', but using the projection approach Craig shows AND relying on something called 'Relationship Fixup' you can get something very similar working:
If you do this:
var projection = from c in ctx.Customers
select new {
Customer = c,
Orders = c.Orders.OrderByDescending(
o => o.OrderDate
)
};
foreach(var anon in projection )
{
anon.Orders //is sorted (because of the projection)
anon.Customer.Orders // is sorted too! because of relationship fixup
}
Which means if you do this:
var customers = projection.AsEnumerable().Select(x => x.Customer);
you will have customers that have sorted orders!
See the tip for more info.
Hope this helps
Alex
You are confusing two different problems. The first is how to materialize entities in the database, the second is how to retrieve an ordered list. The EntityCollection type is not an ordered list. In your example, customer.Orders is an EntityCollection.
On the other hand, if you want to get a list in a particular order, you can certainly do that; it just can't be in a property of type EntityCollection. For example:
from c in northwindContext.Customers
orderby c.SomeField
select new {
Name = c.Name,
Orders = from o in c.Orders
orderby c.SomeField
select new {
SomeField = c.SomeField
}
}
Note that there is no call to Include. Because I am projecting, it is unnecessary.
The Entity Framework may not work in the way you expect, coming from a LINQ to SQL background, but it does work. Be careful about condemning it before you understand it; deciding that it doesn't work will prevent you from learning how it does work.
Thank you both. I understand that I can use projection to achieve what I wanted but I thought there might be an easy way to do it since in T-SQL world it's perfectly possible with a few nested queries (or joins) and order bys. On the other hand seperation of concerns sounds reasonable and we are in the entity domain now so I will use the way you two both recommended though I have to admit this is easier and cleaner to achieve in LINQ to SQL by using AssociateWith.
Kind regards.

Entity Framework and associations between string keys

I am new to Entity Framework, and ORM's for that mather.
In the project that I'm involed in we have a legacy database,
with all its keys as strings, case-insensitive.
We are converting to MSSQL and want to use EF as ORM,
but have run in to a problem.
Here is an example that illustrates our problem:
TableA has a primary string key,
TableB has a reference to this primary key.
In LINQ we write something like:
var result = from t in context.TableB select t.TableA;
foreach( var r in result )
Console.WriteLine( r.someFieldInTableA );
if TableA contains a primary key that reads "A", and TableB contains two rows that references TableA but with different cases in the referenceing field, "a" and "A".
In our project we want both of the rows to endup in the result, but only the one
with the matching case will end up there.
Using the SQL Profiler, I have noticed that both of the rows are selected.
Is there a way to tell Entity Framework that the keys are case insensitive?
Edit:We have now tested this with NHibernate and come to the conclution that NHibernate works with case-insensitive keys. So NHibernate might be a better choice for us.I am however still interested in finding out if there is any way to change the behaviour of Entity Framework.
Thanks for your answer!
Problem is that if we add that constraint to the database now,
the legacy application might stop working because of how it is built.
Best for us would be, if possible, to change the behavior of EF.
I'm guessing it is not possible, but I'm giving it a shot.
Regards,
Fredrik
edit: The reason why I added an answer to my own question was that I added this question before I was a registerd user, and when I had registred my account I couldn't add comments or edit my post. Now the accounts are merged.
I think you need to make the change to the schema in SQL Server, not in EF. This post's answer, on how to make a column case-sensitive, looks like it will do the trick: T-SQL: How do I create a unique key that is case sensitive?
I know this isn't a perfect solution, but in LINQ why not do the join yourself. EF doesn't work because the .Designer.cs file returns objA.Equals(objB) when doing the join. .Equals is case sensitive.
var result = from t1 in context.TableB
join t2 in context.TableA on t1.someFieldInTableB.ToUpper() equals t2.someFieldInTableA.ToUpper();
Hackish I know, but LINQ to Entities is still in its infancy and the object classes that are designed are designed for specific reasons that do not handle exceptional cases in a design such as this.
Another alternative is that you can create your own code generator using T4 templates. Since everything is a public partial class you can create a navigation property that actually does the case insensitive comparisson that you are looking for.
To answer your question truthfully though, there is no "out of the box" way to get EF to do a navigation using case insensitive searching.
I came up with a workaround that "stitches up" the string based association in memory after the context has retrieved the rows from the database (hint: making using of the context.[EntityTypeCollection].Local property. You can see my answer at https://stackoverflow.com/a/12557796/62278
I know this isn't a perfect solution, but in LINQ why not do the join yourself. EF
doesn't work because the .Designer.cs file returns objA.Equals(objB) when doing the >> join. .Equals is case sensitive.
Well, not if you override the Equals method
The generated domain classes in EF are partial no? So it's fairly easy to replace the default Equals implementation of these classes by your own implementations (which of course would render it case insensitive )
BTW : a technique dat dates back from .NET 1.0
With all this .NET 3.5/4.0, Linq and Lambda violence, people tend to forget about the basics
As an alternative to the Entity Framework, you can use LINQ to SQL, which works well with relations involving case sensitive collations. Although this ORM does not offer all the flexibility of EF or NHibernate, it can be sufficient in many cases.
I've recently posted a thread on the official Microsoft Entity Framework forum:
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/d4aa6880-31b3-4ff2-b7f5-e2694d76772e