Get Data from MS Access Database into List<> in C# - c#

Current now i have a List<> of data store string called Diff_ProductName.
List<string[]> Diff_ProductName = ("SELECT GUID,ProductName FROM Table_A bla bla bla.... ");
So i need to use GUID from Diff_ProductName to copy another data from another Table.
For (int i = 0; i < Diff_ProductName; i++)
{
List<string[]> DCB_CopyData = ("SELECT Name, ID FROM Table_B WHERE='"+(((string[])Diff_ProductName[i])[0]+"'");
}
The problems is, every GUID got a few ID and Name. Mean :
TABLE_B
GUID Name ID
1 A 012
1 B 013
1 c 014
2 AB 015
3 D 016
3 E 017
4 ACE 018
4 ADE 019
so when i run the program. The data store at DCB_CopyDate only the last GUID data. Mean at DCB_CopyData only have :
GUI Name ID
4 ACE 018
4 ADE 019
So whats the problems with my code? thanks.

You are executing a query for each GUID and this is painful if your list is really long.
You could simply execute one query like this
SELECT ta.*, tb.* FROM Table_A AS ta
LEFT JOIN Table_B AS tb ON ta.GUID = tb.GUID
About your code: if you're showing us pseudo-code ok, if not your second query seems really wrong sintactically.

Related

Select items with the same foreign key

I have a question regarding Linq in C#.
Let's say that I have 3 tables "Company", "Employee" and "Job".
Company
--------
Id - int (PK)
Name - string
Employee
--------
Id - int (PK)
CompanyId - int (FK on Company.Id)
Name - string
Job
--------
Id - int (PK)
CompanyId - int (FK on Company.Id)
EmployeeId - int (FK on Employee.Id)
Name - string
Something like that:
enter image description here
The important thing is that every work must be connected to a company but not necessarily to an employee. However, each employee must be connected to a company. For example we can have racord like that:
Company
--------
Id Name
1 'A'
2 'B'
3 'C'
Employee
--------
Id CompanyId Name
1 1 'A'
2 1 'B'
3 2 'C'
Job
--------
Id CompanyId EmployeeId Name
1 1 1 'clean'
2 1 2 'wash'
3 2 2 'buy'
4 3 NULL 'sell'
And now with linq I would like to get all jobs that are assigned to this employee and other employees from the same company.
So in this case it will should are jobs with id 1 and 2 becouse employee 1 is assigned to company 1 and job with id 2 also has assigned to this company. How could I achieve this using linq but something like this:
_context.Job.Where (x => x)
It is important to make only one query to the database.
Tkanks.
You can simplify the problem by thinking of it in two steps: find the company for a given employee, find all the jobs for that company:
var companyToFind = from e in Employee
where e.Id == empToFind
select e.CompanyId;
var jobsToFind = from j in Job
where companyToFind.Any(cid => cid == j.CompanyId)
select j;
In LINQ to SQL, EF Core 2.2 and EF Core 3.x the Any is translated to an EXISTS query in SQL.
Note since you know there should be only one answer to companyToFind, sending two queries to the database may be more efficient.
For LINQ to SQL or EF Core 3.x, you could also nest the first query and reduce to a single result:
var jobsToFind = from j in Job
where (from e in Employee
where e.Id == empToFind
select e.CompanyId).First() == j.CompanyId
select j;

Problems in Right join in SQl

I have the following table structure also i have mention my expected output
please help me with query as i dont know much about sql query
Table Structure
Table 1 : Emp Details
FName Id
Pratik 1
Praveen 3
Nilesh 2
Table 1 : JoinigDocument
id DocumentName
1 Leaving
2 Exp letter
3 birth cert
Table 2 : EmployeeJoiningDocument
EmpId JoiningDocumentId
1 1
1 2
3 1
3 2
3 3
2 1
2 3
Expected Output :
FName Id JoiningDocumentId DocumentName
Pratik 1 1 Leaving
Pratik 1 2 Exp letter
Pratik 1 null birth cert
Praveen 3 1 Leaving
Praveen 3 2 Exp letter
Praveen 3 3 birth cert
Nilesh 2 1 Leaving
Nilesh 2 null Exp letter
Nilesh 2 3 birth cert
You can write a query as:
select
A.FName,
A.Id,
B.JoiningDocumentId,
c.DocumentName
from #JoinigDocument C
cross join #EmployeeDetail A
Left join #EmployeeJoiningDocument B on B.EmployeeId = A.id and
B.JoiningDocumentId = C.id
order by A.Id
First cross join JoinigDocument and EmployeeDetail table so that you get all possible combinations of Employee and Documents irrespective of the fact that employee has that Joining Document or not. Then you need to do a left join to retain all these matches and find data corresponding to valid entries in EmployeeJoiningDocument.
Demo

querying key value pair design table using EF

I have a table which is similar to Key-Value pair design structure. I would like to query the table based on the key and value, but I am facing some problem. Below is my table structure and expected output.
Table 1:
ID KEY VALUE
1 NAME abc
2 AGE 12
3 DEPARTMENT CCB
4 NAME xyz
5 AGE 13
6 DEPARTMENT TSS
7 NAME cde
8 AGE 12
9 DEPARTMENT TMS
Table 2:
KeyId KeyName
1 Name
2 Department
3 Age
for easy understanding I entered directly the key names in Table 1, actually there exists a foreign key relation between table 1 and table 2.
Also table 2 can hold anything as KeyName not necessarily Name, Department and Age.
Expected output is : I need to get the data with the Name contains %c% and Age = 12.
Name Age Department
abc 12 CCB
cde 12 TMS
NOTE: I am looking for a EF solution i.e., linq query, not sql query.
Options I tried out, below is the query:
var temp = (from c in table1
where c.Name.Contains("C") || C.Age == 12
Select new { C.Name, C.Age })
Thought of applying "OR" condition so that I get both the condition satisfied and then filter using "AND" in the in-memory once I fetch the data from database. But I was not able to succeed.
Try this:
var result = input.Select((x,i)=>new {x,i})
.GroupBy(a=>a.i/3)
.Where(g=>g.FirstOrDefault().x.Value.Contains("c") &&
Convert.ToInt32(g.Skip(1).FirstOrDefault().x.Value) == 12)
.Select(g=> new {
Name = g.FirstOrDefault().x.Value,
Age = Convert.ToInt32(g.Skip(1).FirstOrDefault().x.Value),
Department = g.Skip(2).FirstOrDefault().x.Value
});
Not sure if it works in EF but looks like if it doesn't, you have to execute the query in client side with AsEnumerable() before appending any method after input.

Column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

This may be a very silly mistake but I just can't fix it. I have 2 tables, Questions and Questions_Rating.
Questions:
question_id question user_id
------------------------------------------
1 'How to blablabla' 1
2 'bla bla bla' 1
Questions_Rating
In this table, users will rate questions either by +1 or -1
question_rating_id question_id user_id rate
------------------------------------------------------
1 1 2 (+1)
2 1 3 (+1)
3 1 4 ( 1)
Now I would simply like to fetch the question from the questions table, and the SUM of the rate in the questions_rating table for this question, which has an ID = 1.
String QUERY = "SELECT q.question, SUM(r.rate) FROM questions q, questions_rating r WHERE r.question_id = q.question_id AND q.question_id = 1";
And this is what I'm getting.
Column 'questions.question' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I know that the SUM of the rate will return 1 row, and the question is supposedly 1 row, I can't figure out what's wrong with this query.
I am using SQL Server 2008.
You will have to Group the values as per the question so you need a
GROUP BY q.question
at the end of your query
Good Explanation here
You need the group by q.question in your SQL statement.
Your Sum is suppose to return only a single row against the table, since you are selecting a column along with the Sum you need to specify a group on the selected column. In your case it should be q.question, and sum will be applied to each group of questions.
SELECT q.question,SUM(r.rate) AS RateSum
FROM questions q,questions_rating r
WHERE r.question_id = q.question_id AND q.question_id=1
GROUP BY q.question
or (using ANSI 92 style joins)
SELECT q.question,SUM(r.rate) AS RateSum
FROM questions q INNER JOIN questions_rating r ON r.question_id = q.question_id
WHERE q.question_id=1
GROUP BY q.question
or (using subqueries)
SELECT q.question, (SELECT SUM(r.rate) FROM questions_rating r WHERE r.question_id = q.question_id) AS RateSum
FROM questions q
WHERE q.question_id=1
You are missing group by clause in your select statement.
As you have used sum() function which is an aggregate function
So you need to write group by for all the select columns.
String QUERY = "SELECT
q.question,
SUM(r.rate)
FROM
questions q,
questions_rating r
where
r.question_id = q.question_id AND
q.question_id=1
group by
q.question";

Possible to write a Join between Sql and DataTable using Linq?

I have a process that extracts customer info from multiple databases (MySql) based on a timestamp. I store this data into a DataTable. The data table represents updates to existing customer info as well as new customer info.
I want to delete any dupes in the destination database (SqlServer) based on one constant value, CompanyID, and the CustomerID. So, I thought a join would give me the RecordIDs of the dupes in the destination DB, pass the List<int> (or some collection mechanism) to the DELETE method.
What I have:
using (var context = new DataContext(SqlConnection))
{
var tblSource = context.GetTable<tblCustomerInfo>();
var dupeIDs = from currCust in tblSource
join newCust in myTable.AsEnumerable() on currCust.CompanyID equals newCust.Field<string>("CompanyID")
where currCust.CustomerID.Equals(newCust.Field<int>("CustomerID")
select currCust.RecordID;
}
This obviously does not work. I will update with the exact error messages in a bit, but this doesn't compile.
First, is my join syntax even correct for what I am wanting to achieve?
Second, how can I write this Linq to join between a DataTable and the destination SqlServer database?
Afterthought - is it possible to, once I have a collection of dupe RecordIDs, use Linq to DELETE records from the destination database?
Edit
To clarify the process, I have incoming data tables like so and contained in a DataSet:
Table1
CompanyID CustomerID Field1 Field2 ....
1 5 ... ...
1 15 ... ...
Table2
CompanyID CustomerID Field1 Field2 ....
10 125 ... ...
10 145 ... ...
Which will all go into a single database:
Destination DB
CompanyID CustomerID Field1 Field2 ....
1 5 ... ...
1 15 ... ...
1 27 ... ...
5 15 ... ...
10 125 ... ...
10 145 ... ...
11 100 ... ...
So, in this case I would delete from the destination table the items that match from tables 1 & 2. The destination database will be growing constantly so creating a List of CustomerID does not seem feasible. However, I expect daily imports of new and updated customer info to be relatively small (in the hundreds, maybe near 1000 records).
If I cannot write a single join what other method for completing this process would be appropriate? I am trying to figure something out since it looks like I cannot actually mix Linq-to-Sql and Linq-to-Objects.
Is it possible to somehow map my data table to the entity datamap, tbl_CustomerInfo, filling an otherwise immutable var, then perform the join?
Update
Here is what I have accomplished at this point and I get the results I expect from dupes:
using (DataContext context = new DataContext(SqlConnection)
{
var custInfo = context.GetTable<tbl_CustomerInfo>();
string compID = ImportCust.Rows[0]["CompanyID"].ToString();
var imports = from cust in ImportCust.AsEnumerable()
select cust.Field<int>("CustomerID");
var dupes = from cust in custInfo
join import in imports
on cust.CustomerID equals import
where cust.CompanyID == compID
select cust;
custInfo.DeleteOnSubmit(/* what goes here */);
context.SubmitChanges();
}
My question now is, what goes into the DeleteOnSubmit(...)? I feel like I have gotten so close only to be foiled by this.
I usually tackle all of this in a stored proc for efficiency.
Add an identity field to your destination table to uniquely identify the records, then use a query like this:
DELETE d
FROM DestinationTable d JOIN (
Select CompanyID, CustomerID, Min(UniqueID) AS FirstRecID
FROM DestinationTable
GROUP BY CompanyID, CustomerID) u on u.CompanyID=d.CompanyID AND u.CustomerID=d.CustomerID
WHERE d.UniqueID <> u.FirstRecID
Alternatively, you could create two lists of List<int>, containing id's from your two sources, then use the Intersect LINQ operator to find the common items.
List<int> a = new List<int>{1,2,3,4,5,6,8, 10};
List<int> b = new List<int>{1,2,99,5,6,8, 10};
var c= a.Intersect(b); //returns the items common to both lists
Here is what I have that works:
using (DataContext context = new DataContext(SqlConnection)
{
var custInfo = context.GetTable<tbl_CustomerInfo>();
string compID = ImportCust.Rows[0]["CompanyID"].ToString();
var imports = from cust in ImportCust.AsEnumerable()
select cust.Field<int>("CustomerID");
var dupes = from import in imports
join cust in custInfo
on import equals cust.CustomerID
where cust.CompanyID== pivnum
select cust;
var records = dupes.GetEnumerator();
while (records.MoveNext())
{ custInfo.DeleteOnSubmit(records.Current); }
context.SubmitChanges();
}
If there is a more efficient method, I'm interested in options.

Categories

Resources