I'm working on an ASP.Net application which uses a SQL-Server DB and database entities.
Further i got three database entities which are dependend on each other.
This is the dependency hierarchy:
Instance (Key: InstanceID)
CustomField (Key: CustomFieldID, InstanceID)
CustomFieldData (Keys: CustomFieldDataID, CustomFieldID)
CustomFieldData_Person (Keys: CustomFieldData_PersonID, CustomFieldDataID)
I can find out the entries from the entity CustomField by this with the InstanceID:
var customFieldEntries = DB_Instance_Singleton.getInstance.CustomField.Where(x => x.InstanceID == instanceId);
Now i want to find out all entries from CustomFieldData_Person which belong to the hierarchy with the InstanceID as key.
In SQL i would write something like this:
SELECT * FROM CustomFieldData_Person WHERE CustomFieldDataID in (
SELECT * FROM CustomFieldData WHERE CustomFieldID in (
SELECT * FROM CustomField WHERE InstanceID = instanceId))
Unfortunately i'm absolutely new to LINQ.
So my question is, how can i write such a nested query in LINQ (aacording to the first code example above)?
Thanks in advance!
Firstly if you create your ER model correctly you will have most of that logic already set up for you
Person would have a property Person.CustomData which would have Properties for Field and Value so you can just navigate the object structure
however if you dont have that then you can just convert the in statements to Contains
CustomFieldData_Person.Where(cfdp=>CustomFieldData.Where(nested query for CustomFieldData).Contains(cfdp.CustomFieldDataID )
I think this link could be a good starting point for your question. Anyway take a look at Pranav's comment, it points to a helpful question
Related
I have an issue with next scheme, I attached it.I want to query from my database with only one object with "Manufacturer" class. Like:
var res = new XPQuery<Manufacturer>(session);
And then query all info that are related to my condition in LINQ.
I have tried XPLiteObject, XPObject, Association attribute, NoForeignKey Attribute, XPOCollection and a lot of stuff but nothing didn't help me.
I have tried a lot of approaches and every time I have new exception like:
SelectMany - method is not supported.
Can't set foreign key in table.
Duplicate primary key.
My question is: how to describe classes for normal extraction data from db?
UPD:
My solution now is: to use .ToList() at every object
and then use linq-query for join data and make needed query.
var manufacturer = new XPQuery<Manufacturer>(session).ToList();
var cars = new XPQuery<Car>(session).ToList();
var countries = new XPQuery<Country>(session).ToList();
var result = from m in manufacturer ....
So, I have found a solution to my question.
I downloaded DevExpress that can add templates for visual studio.
Then I select Add new item to my project named "DevExpress ORM DataModel Wizard".
This wizard can create persistent objects for existing database.
After that I can query database with next syntax:
var manufacturer = new XPQuery<Manufacturer>(session).Select(x => x....)...;
But if you want to use .SelectMany() in your LINQ query you should use .ToList() and then use .SelectMany(). I faced with a lot of issues when I have tried to join or perform some other LINQ related operations. Well, if you got some errors, firstly after .Select() try .ToList() and then perform your operation.
I have the following database structure:
USER <--> [user_client] <--> CLIENT <--> [client_application] <--> APPLICATION
USER, CLIENT and APPLICATION tables contain unique keys. user_client and client_application are many-to-many tables to map USERs to CLIENTs and CLIENTs to APPs.
I am using MVC5 / C#. The many-to-many tables are hidden in my Model by the Entity Framework.
What I want to achieve is the following: for a given USER, which has a list of CLIENTs, get the combined list of the distinct APPLICATIONs that all his CLIENTs have.
Could you please help with the logic and the Linq query (preferably in fluent syntax if possible)? Is it possible to do it in a single query without looping through the list of clients?
Thank you in advance.
Reda
Not sure it matches your schema but what about
user.clients.SelectMany(c => c.applications).Distinct()
The key is to use SelectMany instead of Select which will give you a IEnuerable<Application> instead of a IEnumerable<IEnumerable<Application>>
var user = context.Users.Where(u => u.Id == 1).Single();
var applications = user.Clients
.SelectMany(c => c.Application)
.GroupBy(a = a.Id)
.Select(a => a.First());
I want to collaborate to this question, not providing an exact solution, but additional information.
I applied #tafia answer to my own problem, but with a slight modification to the SelectMany method. I replaced it with just Select.
File selectedFile = _unitOfWork.FileRepository.GetById(idFile)
selectedFile.FilePaper.Select(c => c.Paper).Distinct().ToList()
You can read about the difference between Select and SelectMany, here.
I applied my modified solution on the following group of tables:
Though your table seems to be different:
I'm not sure if that solution proposed by #tafia works there.
PS. If you want to make the middle tables appear in EF, a possible "fix" is adding a primary key to them (id).
I have two tables with a one (Articles) to many (Details) relationship. Details may not contain any data for the particular Article entry.
Articles: Id, Title, Numb (PK), Name
Details: Id (PK), Person, Numb (FK), Name
In the Entity Framework, there are the appropriate Navigation properties and it shows the correct One:Many relationship.
What I want to do is get all Articles that match the end user's query (by 'Name') as well as all, if any, data from the Details table (Id, Person, Numb, Name).
What I'm stuck on is right now I can query Articles just fine (var article = db.Articles.Where(b => b.Name.Equals(name));), but while the result does include a HashSet for Details.Numb on each row of Articles, there is no data in that HashSet. There are appropriate corresponding entries in the database for Article.Numb => Details.Numb.
Actually there is two ways to achieve this.
Enable Lazy Loading.
Call Include method as other answers says.
Using Lazy Loading see msdn article for more detail.
db.ContextOptions.LazyLoadingEnabled = true;
Using Include method
var article = db.db.Articles.Include("Details").Where(b => b.Name.Equals(name))).FirstOrDefault();
You need to tell EF to include the details in the result set after the query is executed (and connection closes):
var article = db.Articles
.Include("Details")
.Where(b => b.Name.Equals(name))
.FirstOrDefault();
Use .Include() on the navigation property, it will bring the entire inner object in the query result. It's only automatic if you filter or select items from the inner object, otherwise you have to manually request an include.
Example:
var allProducts = _db.Products.Include(d => d.Producer).ToList();
Always go with Include instead of lazy loading if you're not sure.
The following code gives me an SqlException: Invalid object name 'dbo.studentsCourses'
OO theCourse = subject.Course;
var students = dc.studentsCourses.Where(x => x.course == theCourse).Select(x => x.student);
I tried the following code instead but I also get an Exception.
My original question was asked on Aardvark and can be read bellow:
var allStudents = from s in dc.students select s;
List thestudents = new List();
foreach (student s in allStudents)
{
if (s.courses.Contains(theCourse))
{
thestudents.Add(s);
}
}
I did a right click, "run custom tool" on my dbml and checked my names of my tables and entities. The project compiles but I get an Exception at runtime on this line:
"if (s.courses.Contains(theCourse))"
Any ideas?
Original question on Aardvark:
How do I do a LinqToSQL query that
gives me this: I want to select all
students that attended a certain
lesson. The lesson is from a certain
course. So select the course the
lesson is from. Now select all the
students that are following that
course. There is a many-to-many
relationship between the students and
the courses table in my DB. I already
extended my LINQ entities to be able
to select student.Courses and
course.Students using this method:
http://www.codeproject.com/KB/linq/linq-to-sql-many-to-many.aspx
Your link to sql classes don't match your db schema or your db does not contain a table or view called studentcourses. You need to adjust either your classes or db so they match.
You could start debugging this problem by visualizing the query that is generated by the LinqToSQL. The Gu has written a blogpost on this a while ago:
http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx
Just copy/paste the query in your favourite database management application and run it against the database. It should become clear what the error is. If there are still some crazy things happening, just update your question?
Hope this helps!
First check your database to see if there is really a table or view name studentsCourses.
If there is then try to regenerate to dbml file and then try again.
I'm not sure... but you may try this one:
var xxx = dc.Include("studentsCourses")
.studentsCourses
.Where(x => x.course == theCourse)
.Select(x => x.student)
.ToList();
I'm sure this is straight forward but I'm very new to entity queries and has probably been asked before.
What i need to to search for all business in my database where they have a category that exists in a collection of categories I have built up
IList<businessCategory> busCatList;
busCatList.Add(businessCategory.CreatebusinessCategory(1,"Tourism"));
busCatList.Add(businessCategory.CreatebusinessCategory(2,"Accomidation"));
busCatList.Add(businessCategory.CreatebusinessCategory(3,"Entertainment"));
busCatList.Add(businessCategory.CreatebusinessCategory(4,"Bar"));
busCatList.Add(businessCategory.CreatebusinessCategory(5,"Club"));
var items = Data.DBEntities.business.Where(b.businessCategory.Contains(busCatList) );
I know the syntax of the query is wrong but essentially what i what the query to do it pull out all the business where it has a category matching any of the categories in the busCatLsit
In my database one business can be linked to many categories
In SQL I would do
SELECT name FROM business
join businessCategoryRlnshp on businessCategoryRlnshp.businessID = business.ID
where categoryID in (1,2,3)
just trying to read your mind here ;)
var items = busCatList.Where(businessCategory => b.businessCategory.Contains(businessCategory));
I can't really imagine a nice solution in linq - I mean other than some kind of performing the query several times - one for each business category.
However in SQL Server 2008 there is a new feature - passing a table variable to stored procedure. This can be done from code by passing a DataSet with 1 DataTable as a parameter.
You can of course write an extension method for IEnumerable to convert it to a DataSet similar to ToList() or ToDictionary() methods.
Stored procedure returning entities can be used in EntityFramework 1.0 so this should theoretically make the puzzle click.
PS> There's also a solution using E-SQL and probably query builder methods.