Using Inner joins in Entity Framework on multiple tables? - entity-framework

I have a student table in my database with columns Id, Name, DepartmentId, CollegeId, CityId etc and a Department table, College table to map to the DepartmentId, CollegeId in the Student table.
Now I want to pass CityId and retrieve Id, Name, DepartmentName, CollegeName with help of the corresponding tables using inner join based on the CityId.
I'm implementing a method FindAll() which takes in CityId as the input parameter and retrieves data based on CityId
public IEnumerable<StudentRegionEntity> FindAll(int CityId)
{
var totalStudents = new List<StudentRegionEntity>();
foreach(var entity in this.Dbcontext.Students)
{
}
}
In the foreach loop I want to bind the list of students with Id, Name, Department, College fields, how can I use joins and implement the functionality for FindAll()?

var studentEntities = this.Dbcontext.Students
.Include("StudentList").Where(s => s.cityId == CityId).ToList()
this will give the list of all the StudentEntity entities with StudentRegionEntity attached, using one join query to the database.

Related

Linq result return zero vs null

Is there a way I have have this linq statement not return nulls ? I would like it to returns 0 I have tried ?? 0 but that is not working
Customer = (from c in db.Customers
join cx in db.CustomerXrefs on c.CustomerId equals cx.CustomerId
join g in db.Groups on cx.GroupId equals g.GroupId
select new Customer
{
CustomerId = c.CustomerId,
Institution = (from ig in db.Groups
join icx in db.CustomerXrefs on ig.GroupId equals icx.GroupId
where icx.CustomerId == c.CustomerId && ig.GroupTypeId == 308
select new Institution()
{
Name = ig.Name == "In1 " ? "Institution 1" :
ig.Name == "In2" ? "Institution 2" :
ig.Name
}
).FirstOrDefault()
}).FirstOrDefault();
It is a bit difficult to distill from your question what you want to achieve. You give us some code, and tell us that the code doesn't do what you want, and ask us to give you the code that does give the requested result.
I hope I can extract your requirement from your code.
It seems that you have a table of Customers and a table of Groups. There seems to be a many-to-many relation between Customers and Groups: every Customer belongs to zero or more Groups, every Group has zero or more Customers that belong to this Group.
In relational databases, a many-to-many relation is implemented using a junction table. The junction table for the many-to-many between Customers and Groups is table CustomerXRefs
For every Customer in the table of Customers, you want its CustomerId, and a Property Institution.
The value of Institution is filled with a Name. This name is taken from the first Group of this Customer with GroupTypeId equal to 308.
There are two solutions for this:
Use GroupJoins to get the Customers with their Groups and extract the Institution from these groups
Use the capability of entity framework to translate the virtual ICollection<...> into the corrrect GroupJoins. Use the virtual properties, entity framework translates them into the proper GroupJoin.
Usually the latter solution is easier, so we'll start with that one first.
The classes
If you have followed the entity framework conventions, you'll have classes similar to the following:
class Customer
{
public int Id {get; set;}
... // other properties
// every Customer belongs to zero or more Groups (many-to-many)
public virtual ICollection<Group> Groups {get; set;}
}
class Group
{
public int Id {get; set;}
public int GroupTypeId {get; set;}
public string Name {get; set;}
... // other properties
// every Group has to zero or more Customers(many-to-many)
public virtual ICollection<Customer> Customers {get; set;}
}
This is enough for entity framework to detect your many-to-many relation. Without even mentioning it, entity framework will create a junction table for you. Only if you want different names of tables or properties, you'll need fluent API or attributes.
In entity framework the columns of the table are represented by non-virtual properties; the virtual properties represent the relations between the tables: one-to-many, many-to-many, ...
Query using the virtual ICollection
var customersWithTheirGroups = dbContext.Customers.Select(customer => new
{
CustomerId = customer.Id,
Institution = customer.Groups.Where(group => group.GroupTypeId == 308)
.Select(group => new Institution
{
name = (ig.Name == "In1") ? "Institution 1" :
(ig.Name == "In2") ? "Institution 2 :
ig.Name,
})
.FirstOrDefault(),
});
BTW: note the parentheses around (ig.Name == "In1"). I think that if Name equals "In1" that you want a name "Institution 1", etc.
Is it correct that you have a class Institution with only one property?
class Institution
{
public string Name {get; set;}
}
Although it is allowed, it is a bit awkward, why not just select the InstitutionName?
.Select(group => (ig.Name == "In1") ? "Institution 1" :
(ig.Name == "In2") ? "Institution 2 :
ig.Name)
.FirstOrDefault(),
Anyway, entity framework knows the relations between the tables and will create the correct groupjoins with the junction tables.
This solution seems very natural.
Solution using GroupJoins
If you want to do the GroupJoin yourself, you'll need to define the junction table:
class CustomerXrefs
{
// every Xref in the junction table belongs to exactly one Customer:
public int CustomerId {get; set;}
// every Xref in the junction table belongs to exactly one Group:
public int GroupId {get; set;}
}
To get each Customer with its Groups, do a GroupJoin of the XRefs with the Customers, followed by another GroupJoin of Groups and XRefs.
var customersWithTheirGroups = dbContext.Customers.GroupJoin(dbContext.CustomerXRefs,
customer => customer.Id, // from every Customer take the Id
xref => xref.CustomerId, // from every xref take the foreign key to Customer
// Parameter resultSelector:
// for every Customer and all its xrefs make one new object:
(customer, xrefsOfThisCustomer) => new
{
Customer = customer,
// To get the Groups of this customer, GroupJoin the Groups with the xrefs:
Groups = dbContext.Groups
// GroupJoin the Group with the xrefs of this Customer
.GroupJoin(xrefsOfThisCustomer,
group => group.Id, // for every Group take the Id,
xRef => xref.GroupId, // for every xref of this customer take the foreign key
// parameter resultSelector:
// for every Group, and all xrefs of this Group that are xrefs of the Customer
// make one new:
(group, xrefs) => group).ToList(),
});
Result: all Customers, each with their Groups.
Select the institution:
var result = customersWithTheirGroups.Select(joinResult => new
{
CustomerId = joinResult.Customer.Id,
Institution = joinResult.Groups
// Keep only the Groups with the desired GroupTypeId
.Where(group => group.GroupTypeId == 308)
// The Select is similar as the Select in the virtual ICollection method:
.Select(group => new Institution
{
name = (ig.Name == "In1") ? "Institution 1" :
(ig.Name == "In2") ? "Institution 2 :
ig.Name,
})
.FirstOrDefault(),
});
Customer is a class (reference type). Default value for a reference type is null. If you want to return some non null value (if there exists correct "default" for your use case) you will need to provide one, for example:
Customer = (...).FirstOrDefault() ?? new Customer();

How to retrieve list of objects by list of fields

Table user has following schema
id integer PRIMARY KEY,
name varchar(120) NOT NULL,
ssn integer NOT NULL
Spring Data JPA provides following in CrudRepository interface to retrieve one user based on id
Optional<User> findById(Integer id);
But I want to retrieve all User.names,given an list of id's (assume list has no repetions); how can I retrieve their names. I know I can loop the above findById, but that is not practical when table size is very big
Use findByIdIn for find by the list of ids and get the user list.
List<User> findByIdIn(List<Integer > ids);
And for only get names of users of given ids
#Query(value = "SELECT c.name FROM User c WHERE id IN (?1)")
public List<String> findAllNames(List<Integer> ids);

C# EF query for typical products - category relationship?

Using entity framework, trying to get some help for a query (prefer method based syntax) for this typical use case:
There is a products table, like:
ownerId
productId
ProductCategoryId
productInfo, etc.
There is a typical product-category-mapping table, like:
somePrimaryKey
ownerId
categoryId
productId
sortOrder
This set up allows one product to be in multiple category, and has its own sort order in each category. Also, we have the "ownerId" in all tables since each owner can only see his own data.
Now, given a categtoryId and ownerId, we need to find all products of this category, sorted by the sortOrder.
Any way how we should write this?
Many Thanks!
You can try to use something along those lines :
// Instanciate your context.
// Do it the way you've already done it, it's here only for example.
DbContext bd = new DbContext();
// The query :
List<Products> listProducts = new List<Products>();
listProducts = db.Products.Where(p => (db.ProductsCategories.Where(pc => pc.CategoryID == categoryID && pc.OwnerID == ownerID).Select(pc => pc.ProductID).OrderBy(pr => pr.sortOrder).ToList()).Contains(p.ProductID)).ToList();
This way use the product-category mapping (categorieID and ownerID are the datas you inject and you keep the sorting.

How to create association one to many and many to one between two entities in gorm?

I'm new in Grails. I have a problem with generation association many to one and one to many between two tables. I'm using postgresql database.
Employee.groovy
class Employee {
String firstName
String lastName
int hoursLimit
Contact contact
Account account
Unit unit
char isBoss
static hasMany = [positionTypes:PositionType, employeePlans: EmployeePlan]
}
EmployeePlan.groovy
class EmployeePlan {
AcademicYear academicYear
HourType hourType
int hours
float weightOfSubject
Employee employee
static belongsTo = [SubjectPlan]
}
I'd like to have access from employee to list of employeePlans and access from EmployeePlan to Employee instance. Unfortunately GORM generates only two tables Employee and EmployeePlan with employee_id. I don't have third table which should have two columns employee_id and employee_plan_id. Could you help me ?
I think your setup is correct, as you write from Employee class you can access to a collection of EmployeePlan (take care, that if you don't explicitly define EmployeePlan like a List, it will be a Set by default) and from EmployeePlan you can access Employee.
If you need List, you can define it like that:
class Employee {
String firstName
String lastName
int hoursLimit
Contact contact
Account account
Unit unit
char isBoss
//explicitly define List
List<EmployeePlan> employeePlans
static hasMany = [positionTypes:PositionType, employeePlans: EmployeePlan]
}
But back to your question. You'd like to have join table between Employee and employeePlan, but why? Its not necessary, since you have bidirectional mapping with sets (unordered), grails will not create a join table. Can you explain why do you need it? In grails the references will be auto-populated, so I don't see any issue here.
If need to preserve order of employeePlans, then define it as List, shown above, and grails will create a join table with corresponding indexes.
have you read the ref-doc? it gives you the answer immediately:
class Person {
String firstName
static hasMany = [addresses: Address]
static mapping = {
table 'people'
firstName column: 'First_Name'
addresses joinTable: [name: 'Person_Addresses',
key: 'Person_Id',
column: 'Address_Id']
}
}

Entity Framework Return Parent along with child entity as Ieunmerable List

I am new to Entity Framework and had a question i have been stuck on for a while. I have a repository in my DAL to access the data its returning IEnumerable lists for functions defined there. There are two tables involved here table Company and thier Customer_orders please see below for details. I need to return an Ienumerable list for Customer Orders ...which also includes the Customer name. I am able to return everything back for the customer order table but cant get the Customer name from the related table. Is it because I am returning a list of Ienumerable CustomerOrder type? If anyone can provide some help by showing the right code it would be greatly appreciated. Once again I am trying to bind to a grid pulling from the CustomerOrders table but need to also display CustomerName from Customers table.
Table1 (Customers)
company_id
customer_id
customerName
customerAddress
Table 2 (CustomerOrders)
customer_id
product_id
productName
productDesc
This is what I have so far this doesnt pull up any customer Names but pulls the CustomerOrders information
public IEnumerable<CustomerOrders> GetCustomerOrders(int company_id)
{
return context.Customers.Where(c => c.company_id == company_id).First().CustomerOrders.ToList().OrderBy(p => p.ProductName);
}
How about:
return context.CustomerOrders
.Include(o => o.Customer)
.Where(o => o.customer_id == customer_id);