How to loop through tables from SQL in c# without hardcoding - c#

I'm creating a desktop application. I have 3 table (part time employees table, full time employees table and department table). The ID on department table is the foreign key.
I have created a connection string in my class. I'm trying to loop through the tables to get all departments that are assigned to employees, if a department is not assigned (delete it). I have the code in sql, but I want it in c#. Below is the sql code.
SELECT DepartmentName, DepartmentAddress
FROM Department
WHERE ID IN
(SELECT DISTINCT(ID)
FROM
PartTimeEmployees
);

If you simply want to DELETE departments that don't have a related employee, you can use an EXISTS:
DELETE D
FROM dbo.Department D
WHERE NOT EXISTS(SELECT 1
FROM dbo.Employee E
WHERE E.DepartmentID = D.ID);
There's no need to go any kind of "looping", as SQL is far better at doing these operations in a set-based way.

If deleting department not in part time employees table or full time employees table then you can get the department list as -
var departmentToDelete = departments.Where(d => !PartTimeEmployees.Any(emp => emp.DepartmentId == d.Id) && !FullTimeEmployees.Any(emp => emp.DepartmentId == d.Id)).ToList();

Related

Create a table in SQL Server where the name is a variable in C#?

Using Visual Studio and SSMS.
I have a form where a user registers a username and it's stored like this:
List<SqlParameter> sqlNewTable = new List<SqlParameter>();
sqlNewTable.Add(new SqlParameter("Username", txtUser.Text));
DAL.ExecSP("CreateUserCourses", sqlNewTable);
From there, can I create a stored procedure called CreateUserCourses in which it creates a new table where the users input (their username) is the name of a new table?
Sure you can, but why?
Supposing you have a User table and a Course table. Then just make a 3rd table which maps those tables together Called UserCourses. This is called a Many-to-Many (mapping table) and it will containing an ID of both the User, and Course and any other relevant information .
This will make your life a lot easier going forward
Many-to-many (data model)
A many-to-many relationship is a type of cardinality that refers to
the relationship between two entities1 A and B in which A may
contain a parent instance for which there are many children in B and
vice versa.
For example, think of A as Authors, and B as Books. An Author can
write several Books, and a Book can be written by several Authors
Example
student: student_id, first_name, last_name
classes: class_id, name, teacher_id
student_classes: class_id, student_id // mapping table
SQL queries could look like this
Getting all students for a class
SELECT s.student_id, last_name
FROM student_classes sc
INNER JOIN students s ON s.student_id = sc.student_id
WHERE sc.class_id = X
Getting all classes for a student
SELECT c.class_id, name
FROM student_classes sc
INNER JOIN classes c ON c.class_id = sc.class_id
WHERE sc.student_id = Y
Entity framework queries could look like this
Getting all students for a class
var students = db.Students.Where(x => x.StudentClasses
.Any(y => y.ClassId == 1);
Getting all classes for a student
var classes = db.classes.Where(x => x.StudentClasses
.Any(y => y.StudentId == 1);

Outerjoin with a table of foreign keys in EF Data-first approach

I have a table Users which contain user information. I have a table Products which contain product information. I have a table called UserProduct which acts as a junction table and whose fields are UserId and ProductId. I am using a Entity Framework database first approach.
I want to outerjoin using Linq to find the following data.
All Users in the Users table.
All Users who have bought a particular product in terms of a Boolean called isPurchased.
My thinking was to left outer join table User with UserProduct and get all users and whether they have a product something like this.
var result = from a in Users
join b in UserProduct(Not available through EF) on a.Id equals b.prodId into group1
from g1 in group1.DefaultIfEmpty()
select new
{
id = g1.Id,
isPurchased = g1.prodId != null
}.ToList();
However in EF mapping, the object UserProduct is not created and so I cannot use it directly in my Linq query? So how do I go about this? Is there a way I can use linq to join tables with the actual table name(UserProduct) instead of joining entities?
Assuming Users contains a property List<Products> products to represent the junction information, and a variable boughtProductId to represent the particular product:
var result = from u in Users
let isPurchased = u.products.Any(p => p.Id == boughtProductId)
select new {
id = isPurchased ? boughtProductId : null,
isPurchased
}.ToList();

nhibernate: join tables for order by

I have an interesting scenario. I have 2 tables say 'Order' and 'Delivery'.
Order has columns- Orderid, Numberofunits , personID , cost ,orderdate, status
Delivery's Columns- DeliveryID , address, Deliverydate , personID
personID does not have a one to many (or many to many ) property.
mappings and classes of 'order' and 'delivery' are part of the bigger project which cannot be changed.( changing this would mess up lot of other parts of the project.)
Now i have a query
Order orderalias = null;
var order = session.QueryOver<Order>(() => orderalias )
.Where(() => orderalias .Status == orderalias .Ready)
.OrderBy(() =>orderalias.orderdate).Asc
.Take(4)
.List();
But i have to order by deliverydate joing 2 tables. I tried using joinalias but obviously does not allow me to do it. (i got not an association: error)
I tried using 'WithSubquery.WhereExists' but i cannot use deliverydate outside subquery. Is there a way i can join and order this without changing the mapping and the class ?
I would like the query to be like
select delivery.* from delivery
join order on order.personID = delivery.personId
where order.status = 'ready'
order by order.orderdate, delivery.deliverydate

How to write linq query comparing 2 tables?

Okay so I have a database that has a Projects, Users and ProjectMembers table, the Projects table has an ID column and ProjectOwner column which is a foreign key from the Users table, the Users table has ID, username columns and the ProjectMembers table has an ID, ProjectID and UserID column with the later 2 columns being foreign keys from the Projects table and Users table.
Basically the project is something that manages projects, a user can create a project which makes them the owner and then other users can be assigned to that project which adds a record to the ProjectMembers table.
I'm trying to write a linq query that selects all records from the Projects table where a specific user isn't the ProjectOwner but they are a ProjectMember in the ProjectMembers table?
I've made various attempts but so far haven't been able to get the query right.
Something like this should work:
from p in Projects
join m in ProjectMembers on m.ProjectID equals p.ID
where m.UserID == userID && p.ProjectOwner != userID
group p by p.ID
select p
You can make several from clauses:
from e1 in table1
from e2 in table2
where e1.key == e2.id
select e1.name
Try this:
from x in Users
where ProjectMembers.Any(y => y.UserID==x.ID) &&
!ProjectOwners.Any(z => z.ProjectOwner==x.ID)
select x;

Linq to Sql - Populate JOIN result into a List

I am not sure if this can be done, but here's the scenario.
I want to turn this sql into linq:
SELECT * FROM Department d
INNER JOIN Employee e ON e.DepartmentID = d.DepartmentID
Department - Employee is 1 to many relationship.
I have created a custom object that I would like to populate the result into.
public class DepartmentSummary
{
public Department Department { get; set; }
public List<Employee> Employees {get; set;}
}
The Linq I came up with is
var result = from d in dba.Department
join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1
select new DepartmentSummary
{
Department = d,
Employees = j1.ToList()
};
I tried it out and it's not working. Can anyone shed some light for me please? I would like to perform an inner join between Department and Employee. For each Department in the resultset, I would like to create one DepartmentSummary object which holds that department and a list of employees belonging to that department.
Does Linq provides an ad hoc solution for this or must I iterates through the result set and create a list of DepartmentSummary manually?
Thanks,
EDIT:
Looks like this works for me
var result = from d in dba.Department
join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1
where j1.Count() > 0
select new DepartmentSummary
{
Department = d,
Employees = j1.ToList()
};
The thing is that you're not really taking one SQL and trying to create a Linq-query out of it.
If you were, you'd notice that your SQL query does not really produce one row per department, but it will repeat the department information for each employee in that department.
Now, an initial naive look would suggest you use a group-by clause, since that would allow you to split the data into individual groupings for each department, but groupings in SQL does not really give you a key+all-matching-rows type of result, rather it allows you to do aggregate calculations, like "for each department, how many employees do I have".
So, in order to do what you want, you need to basically do a normal join, which will give you each employee, coupled with the appropriate department information (ie. each employee will be linked to his/her department), and then you need to construct the rest of the data structure yourself.
Now, having said that, if you have the proper relationships set in your data context related classes, each department should already have some kind of property that contains all employees in that department, so perhaps the simple query is just "give me all departments", and then you can, for each department, retrieve the employees?
Of course, doing that would likely execute one SQL for each department, but in this case, you're back to "give me all employees with their department information" and you have to build code to handle the rest.
LINQ to SQL doesn't understand your ToList() call, but you might be able to select the sequence of joined elements and then use LINQ to Objects (via AsEnumerable()) to map to your DepartmentSummary object:
var qResult = from d in dba.Department
join e in dba.Employee d.DepartmentID equals e.DepartmentID into j1
select new
{
Department = d,
Employees = j1
};
var result = from d in qResult.AsEnumerable()
select new DepartmentSummary()
{
Department = d.Department,
Employees = e.Employees.ToList()
};
Sounds like you're looking to get around lazy loading?
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Department>(d => d.Employees);
using (var dba = new MyDataContext())
{
dba.LoadOptions = dlo;
var result = from d in dba.Department
select d;
}
Now, if you don't have a relationship defined between Department and Employees (the Linq2Sql designer will do this for you if you have database relationships setup) then you should look into doing that. It makes it all dramatically easier. In fact, you don't even need your campaign summary.
This problem is due to the nature of the query. When you join Department to Employee, you'll get back one record for every Employee. This means that your ToList() statement is expecting multiple employees per department, but due to the join, always getting one.
Change your query to
var result =
from d in dba.Department
select new tCampaignSummary
{
Department = d,
Employees = dba.Employee.Where(e => e.DepartmentID ==
d.DepartmentID).ToList()
};
I've tested this and it works.
What it does differently is selects only one record per Department (not per employee) then it gets the zero to many corresponding employees for each dept and converts them to a list.
Good luck!
EDIT
As requested, here is the generated SQL:
SELECT [t0].*, [t1].*
(
SELECT COUNT(*)
FROM [dbo].[Employee] AS [t2]
WHERE [t2].[DepartmentID] = [t0].[DepartmentID]
) AS [value]
FROM [dbo].[Department] AS [t0]
LEFT OUTER JOIN [dbo].[Employee] AS [t1]
ON [t1].[DepartmentID] = [t0].[DepartmentID]
ORDER BY [t0].[DepartmentID], [t1].[IndexID]
The only modification is that LINQ will not do [t0].*, instead it will enumerate each field. Since I had to guess at the fields, I left them out to make the SQL clearer.

Categories