I am beginner with EF and Linq, so I would like to know the difference and the advantages to use one or the other approach, for example I can see to get data between two tables that it is possible use something like that:
var usr = from cm in ctx.ConsumerName
join c in ctx.Consumer on cm.ConsumerId equals c.Id
where cm.ConsumerId == consumerId
select new { Nombre = cm.FirstName + cm.LastName, Email = c.Email };
likewise, something like that is possible:
var usr = ctx.ConsumerName.Include(x=>x.Consumer);
or something like that as well:
var consumer = ctx.Consumer.Find(id);
var vm = new ConsumerViewModel();
Mapper.CreateMap<Consumer, ConsumerViewModel>()
.ForMember(dest => dest.Consumer, opt => opt.MapFrom(src => src));
vm = Mapper.Map<Consumer, ConsumerViewModel>(consumer);
Can someone explain me which is the best approach to get data from my data base with MVC and EF??? Thanx
There are a number of different ways to create and execute query with Entity Framework, such as LINQ, Entity SQL, etc.
LINQ to Entities is mostly commonly used, I think it's a good way to get data from a database using EF.
You can learn more bout LINQ here:
http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
From the code examples you provided, I think you're not very clear on what LINQ and Entity Framework is.
var usr = from cm in ctx.ConsumerName
join c in ctx.Consumer on cm.ConsumerId equals c.Id
where cm.ConsumerId == consumerId
select new { Nombre = cm.FirstName + cm.LastName, Email = c.Email };
Above is a LINQ query with join operator.
var usr = ctx.ConsumerName.Include(x=>x.Consumer);
Above is Eagerly Loading. Entity Framework supports three ways to load related data, eager loading, lazy loading and explicit loading.
var consumer = ctx.Consumer.Find(id);
var vm = new ConsumerViewModel();
Mapper.CreateMap<Consumer, ConsumerViewModel>().ForMember(dest => dest.Consumer, opt => opt.MapFrom(src => src));
vm = Mapper.Map<Consumer, ConsumerViewModel>(consumer);
Above is mapping collection of entities in EF with AutoMapper.
If you want to learn more about Entity Framework, take look at below link, there are many great articles
written by experts.
http://msdn.microsoft.com/en-US/data/ee712907#ef6
Related
I have an MVC 3 project in Visual Studio c#. I have a LINQ to SQL query which works fine and by following an example listed elsewhere on stackoverflow:
Comparing two lists using linq to sql
I have been able to successfully reduce my results where my two nested collections match. This is the bit of code that did the trick (example from the link above):
var anyDesiredSkills = canidateSkills.Any( c => desiredSkills.Select( ds => ds.SkillId ).Contains( c.SkillId ) );
I've adapted this successfully, but now I need to be able to filter records using more than one condition. I was wondering if anyone would be able to adapt the above to show how you could include more than one condition?
To give you some background on what my goal is:
A search page where you can select any number of contacts
Each contact added to the search criteria may/may not have a 'role' assigned. If a role is present this should be factored in to the query.
Results returned based on this dynamic criteria.
Thanks in advance for any and all help :O)
It sounds like you're looking for something like:
var desiredSkillIds = desiredSkills.Select(_=>_.SkillId).ToList();
var matchingContacts =
from contact in Contacts
where contact.Role == null || desiredRoles.Contains(contact.Role)
where contact.Skills.Any(cs=> desiredSkillIds.Contains(cs.SkillId))
select contact;
Or in method-based syntax:
var matchingContacts = Contacts
.Where(contact => contact.Role == null || desiredRoles.Contains(contactRole))
.Where(contact => contact.Skills.Any(cs => desiredSkillIds.Contains(cs.SkillId)));
Here's the final code I used:
servicelist = servicelist.Where(
d => d.ContactSelection.Any(
h => model.ContactFilter.Select(ds => ds.StaffNumber).Contains(h.StaffNumber)
&&
model.ContactFilter.Select(ds => ds.ContactRole).Contains(h.ContactRole) || model.ContactFilter.Select(ds => ds.StaffNumber).Contains(h.StaffNumber) && model.ContactFilter.Select(ds => ds.ContactRole).Contains("0"))
);
Note that the last filter .Contains("0) is the value of '-- select role --' which is an option injected in to the drop down. Hope this helps anyone else!
I'm attempting to write a search function for a database table that needs to access information from related tables using Entity Framework. However, I'm running into problems getting the data back out of my initial query after doing a join on the parent table and the related tables. My code currently looks like this. I initialize my queryable object
IQueryable<PurchaseOrder> po = _context.PurchaseOrders;
Where PurchaseOrder is an Entity type. Then there is a series of blocks like this.
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
var helper = _context.PurchaseOrderComments.Where(x => x.CommentText.Contains(searchViewModel.Comment));
var mid = po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) =>
new
{
PurchaseOrderID = r.PurchaseOrderID,
PurchaseOrderNumber = r.PurchaseOrderNumber,
VendorID = r.VendorID,
ContractNumber = r.ContractNumber,
BuyerUserID = r.BuyerUserID
});
po = mid.Select(x => new PurchaseOrder
{
PurchaseOrderID = x.PurchaseOrderID,
PurchaseOrderNumber = x.PurchaseOrderNumber,
VendorID = x.VendorID,
ContractNumber = x.ContractNumber,
BuyerUserID = x.BuyerUserID
});
}
After each block, po is passed to the next search parameter. However, as you might guess, my program complains that I can't build a complex type in mid's Select statement. I've also tried building PurchaseOrder objects from the contents of mid, inserting them into a new List of PurchaseOrders, and converting that list into a queryable to assign to po to pass on to the next block. However, that changes po's data type from System.Data.Object.ObjectSet to System.Collections.Generic.List, which then throws an InvalidOperationException the next time I try and iterate through it using a foreach.
So my question is, are there any obvious mistakes in my approach or any suggestions for other ways to approach the problem? Thanks very much for any help.
I think you're making this more complicated than it needs to be. If I understand what you're trying to do, you should be able to do something like this:
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
po = po.Where(
o => o.PurchaseOrderComments.Any(
c => c.CommentText.Contains(searchViewModel.Comment)));
}
StriplingWarrior's solution is the best way. In case that your PurchaseOrder class really doesn't have a navigation collection of PurchaseOrderComments (which would force you to use a join) the following should work and is simpler as your double projection:
po=po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) => r);
I have the following query working which gets the results I want:
int associatedId = 123;
MyObject alias = null;
var subQuery = QueryOver.Of<DatabaseView>()
.Where(view => view.AssociatedId == associatedId)
.And(view => view.ObjectId == alias.ObjectId)
.Select(view => view.ObjectId);
var results = session.QueryOver<MyObject>(() => alias)
.WithSubquery.WhereExists(subQuery)
.List();
The DatabaseView has been mapped as an actual NHibernate entity (so I can use it with QueryOver), but it is not associated to MyObject in the HBM mappings.
This query returns an IList<MyObject> using a SELECT ... FROM MyObject WHERE EXISTS (subquery for DatabaseView here). How can I re-write this to return the same data but using a JOIN instead of sub query?
In NHibernate 5.1+ it's possible for QueryOver/Criteria via Entity Join:
int associatedId = 123;
MyObject alias = null;
DatabaseView viewAlias = null;
var results = session.QueryOver<MyObject>(() => alias)
.JoinEntityAlias(() => viewAlias, () => viewAlias.ObjectId == alias.ObjectId && viewAlias.AssociatedId == associatedId)
.List();
Criteria example:
int associatedId = 123;
var results = session.CreateCriteria<MyObject>("alias")
.CreateEntityAlias(
"viewAlias",
Restrictions.EqProperty("viewAlias.ObjectId", "alias.ObjectId")
&& Restrictions.Eq("viewAlias.AssociationId", associatedId),
JoinType.InnerJoin,
typeof(DatabaseView).FullName)
.List();
You can join onto unrelated entities with Linq in NHibernate 3+
Funnily enough you use the join query expression element:
from type1 in Repository.Query<MyType1>()
join type2 in Repository.Query<MyType2>()
on type1.Id equals type2.Id
Note: Repository.Query is just returning an IQueryable Query from the session
I'm hoping there is a solution for QueryOver as I don't always want to model two-way relationships in my domain but they are still useful for querying.
Also, you can map a Access="noop" 2 way relationship using Criteria API without putting into your POCO classes:
http://ayende.com/blog/4054/nhibernate-query-only-properties
I realize this question is 5 years old, and the "correct" answer is definitely that you can't do this with QueryOver, as the other answers indicate. However, if you really need this functionality (as I did), there is a decent workaround that I found.
The solution is to use a "loader query" with native SQL in your mapping XML to produce a related collection (see http://nhibernate.info/doc/nhibernate-reference/querysql.html#querysql-load). In the OP's specific example, you would go ahead and map your DatabaseView as an entity as suggested, and then write the following in your mapping:
<class name="MyObject"...>
...
<set name="MyViews" inverse="true">
<key column="ObjectId" foreign-key="none"/>
<one-to-many class="MyObject"/>
<loader query-ref="myObjectViewsLoadQuery"/>
</set>
</class>
Then we just need to define our named myObjectViewsLoadQuery in raw SQL to explain to NH how to join the two:
<sql-query name="myObjectViewsLoadQuery">
<load-collection alias="view" role="MyObject.MyViews"/>
SELECT view.*
FROM DatabaseView view
WHERE view.ObjectId = :id
</sql-query>
We can now pretend like there is a "real" collection named MyViews relating MyObject to DatabaseView in our query:
MyObject alias = null;
DatabaseView view = null;
var results = session.QueryOver<MyObject>(() => alias)
.JoinAlias( () => alias.MyViews, () => view )
//.Where( () => view.Property == "myValue" ) // optionally, restrict the view etc.
.List();
Certainly, this is a lot of trouble to go through if you only care about an "elegant" query. However, if the reason you are using QueryOver is that you want to be able to accept arbitrary input Expressions to filter your DatabaseView by, or various similar activities, this works very nicely.
Not sure how this is done, I have my .edmx set up so that the navigation properties match the foreign key relationships on the tables. Not sure if I still need to perform joins or if EF will give me access to the related table data through the navigational properties automatically.
What I need to do it get all the ContentSections and their associated ContentItems based on the ContentView and filtered by the DiversionProgram.CrimeNumber.
I would like to get back IEnumerable, for each ContentSection it should have access to it's ContentItems via the navigation property ContentItems
Thanks
Something like:
using(Entities context = new Entities())
{
IEnumerable<ContentSection> enumerator = context.ContentSections
.Include("ContentItems")
.Where<ContentSection>(cs => cs.ContentView.ContentViewID == someID && cs.ContentItems.Where<ContentItem>(ci => ci.DiversionProgram.CrimeNumber == someCrimeNumber))
.AsEnumerable<ContentSection>
}
I've interpreted
based on the ContentView
as cs.ContentView.ContentViewID == someID
This will give you all the ContentSections for a given ContentView. And interpreted
filtered by the DiversionProgram.CrimeNumber
as cs.ContentItems.Where<ContentItem>(ci => ci.DiversionProgram.CrimeNumber == someCrimeNumber)
which will give you all those ContentItems that have a specific CrimeNumber.
Or did you mean something else with based on / filtered by. Maybe OrderBy, or all those ContentSections where Any of it's ContentItems would have a certain CrimeNumber?
You can eager load to get all associated records, but when you want to start filtering/ordering, don't bother with Include.
Just do a projection with anonymous types and EF will work out what it needs to do. It's a bit hairy, but it'll work. If it get's too complicated, bite the bullet and use a SPROC.
Now, with that caveat, something like this (off the top of my head):
var query = ctx.ContentView
.Select(x => new
{
ContentSections = x.ContentSections
.Where(y => y.ContentItems
.Any(z => z.DivisionProgram.CrimeNumber = 87))
}).ToList().Select(x => x.ContentSections);
If you use the CTP5 you can do something very unique it looks like this:
var context = new YourEntitiesContext();
var query = context.ContentView.Include(cs => cs.ContentSections
.Select(ci => ci.ContentItems
.Select(dp => dp.DiversionProgram)
.Where(dp.CrimeNumber == crimeNumber)))
.Where(cv => cv.ContentViewID == contentViewID).FirtsOrDefault();
You can learn more about the CTP5 and how it can be used in Database first scenario here
var query = from t1 in studentManagementEntities.StudentRegistrations
join t2 in studentManagementEntities.StudentMarks
on t1.StudentID equals t2.StudentID
select new
{
t1.selected column name,
t2.selected column name
};
Hi
How can i filter results exists in BindingSource filled with entities ( using EF 4)?
I tried this:
mybindingsource.Filter = "cityID = 1"
But it seems that binding source with entity framework doesn't support filtering .. am i right ?,is there another way to filter(search) data in binding source .
PS:
- I'm working on windows application not ASP.NET.
- I'm using list box to show the results.
Thanx
Maybe a better one than Leonid:
private BindingSource _bs;
private List<Entity> _list;
_list = context.Entities;
_bs.DataSource = _list;
Now when filtering is required:
_bs.DataSource = _list.Where<Entity>(e => e.cityID == 1).ToList<Entity>;
This way you keep the original list (which is retrieved once from the context) and then use this original list to query against in memory (without going back and forth to the database). This way you can perform all kinds of queries against your original list.
I think, you have made mistake in syntax. You should write Filter like this:
mybindingsource.Filter = "cityID = '1'"
Another way is to use LINQ expressions.
(About LINQ)
Why do you have to call Entety again?
Simple solution:
public List<object> bindingSource;
public IEnumerable FiltredSource
{
get{ return bindingSource.Where(c => c.cityID==1);
}
.where (Function (c) c.cityID = 1)