Update query's where clause values from a datatable - c#

I have this query:
UPDATE A
Set A.NUM = B.NUM
FROM A
JOIN B on A.ID = B.ID
where A.Code in ()
A.Code values are from a datatable. How do I feed into this query?

Why not write a code to make a comma separated string of ID's using datatable?
string lstOfIDs = string.Empty;
DataTable dt = new DataTable();
foreach (DataRow drow in dt.Rows)
{
lstOfIDs += drow["IdColumnHere"].ToString()+",";
}
lstOfIDs.TrimEnd(',');
You can then pass the lstOfIds in the IN clause.
EDIT 1:
I think A.Code In () is checking for code not Ids. I hope you are placing codes in the lstOfIDs. Also, I would advise putting ' between Id's. i.e.
lstOfIDs += "'"+drow["IdColumnHere"].ToString()+"',";
this should give you something like 'abc','def','anything'

You want a Table-Valued Parameter.
This article will also help:
http://www.brentozar.com/archive/2014/02/using-sql-servers-table-valued-parameters/
If you have more columns than just Code in the C# Datatable, you may also need a projection (inside the sql) get output that will work with the IN() clause. Something like this:
UPDATE A
Set A.NUM = B.NUM
FROM A
JOIN B on A.ID = B.ID
where A.Code in ( SELECT Code FROM #tvpCodes )

Related

Filter out a DataTable by avoid some of its distinct columns

I have a DataTable named dtEmployee with four columns, viz. EmployeeId, EmployeePosition, SupervisorPosition, SupervisorId which all are of type varchar(10).
I want to filter the results in dtEmployee whose result is equivalent to SQL Query below.
Select * from dtEmployee where EmployeePosition not in (Select distinct SupervisorPosition
from dtEmployee);
I have achieved the sub query equivalent by creating another DataTable named dtDistinctSupervisors as
dtDistinctSupervisors = dtEmployee.DefaultView.ToTable(true, "SupervisorPosNum");
This is equivalent to Select distinct SupervisorPosition
from dtEmployee
How can I get the whole query equivalent.
Your help is appreciated. Thanks.
Merin
Having Distinct inside an IN subquery makes no difference. This should dot it:
var dt = dtEmployee.AsEnumerable();
var result = dt.Where(emp => !dt.Any(sup =>
sup.Field<string>("SupervisorPosition") ==
emp.Field<string>("EmployeePosition")));
And to show the result in the Console:
foreach (DataRow row in result) // Loop over the rows.
{
Console.WriteLine("--- Row ---");
foreach (var item in row.ItemArray)
{
Console.Write("Item: ");
Console.WriteLine(item);
}
}

C# DataTable Linq select distinct values where column equals 'x'

I have a Datatable (Groups) designed like so
ColumnA|ColumnB
X|Apple
Y|Purple
X|Apple
X|Mango
I basically want to select from columna where it's X and get the disinct from ColumnB
This is what I have
var names = (from DataRow dr in Groups.Rows
orderby (string)dr["ColumnB"]
select (string)dr["ColumnB"]).Distinct();
This will give me distinct but it gives me Purple, and i dont want purple.
Thanks!
var names = (from DataRow dr in Groups.Rows
where dr["ColumnA"] == "X"
orderby (string)dr["ColumnB"]
select (string)dr["ColumnB"]).Distinct();
DataTable dt2 = dt1.Select("ColumnA = 'X'").CopyToDataTable().DefaultView.ToTable(true, "ColumnB");
So here we are selecting only the rows of data that you want, only rows where columnA is X. Then we choose only to see columnB, but with unique values only. Doing it in this order, you'll receive another datatable to play with. It'll only contain 1 column, columnB, and it'll only have unique/distinct values.
Enjoy.
If your return has more than one value and you want to Distinct the whole set by just one of the values you should use a custom IEqualityComparer.
var names = (from DataRow dr in Groups.Rows
where (string)dr["ColumnA"] == "X"
orderby (string)dr["ColumnB"]
select new {
ColumnA = (string)dr["ColumnA"],
ColumnB = (string)dr["ColumnB"]
}).Distinct(new MyCustomEqualityComparer());
edit: to include where clause
edit2: changed to custom IEqualityComparer

How can I use sql Aggregate functions in C# DataTable

I want to apply the follwing Sql query in my DataTable
SELECT MakeDistinct AS AfterDistinct
, COUNT(MakeDistinct) AS Count
FROM MyTable
GROUP BY MakeDistinct
Refer this Question for more details
something like:
var query = from row in table.AsEnumerable()
group row by row.Field<int>("MakeDistinct") into grp
select new {AfterDistinct = grp.Key, Count = grp.Count()};
foreach(var row in query) {
Console.WriteLine("{0}: {1}", row.AfterDistinct, row.Count);
}
Note that aggregating at the database server will usually be much more efficient than populating a DataTable over the network and then aggregating the DataTable.
You are partially looking for DataTable.Compute. That method can calculate aggregate functions for you. So you get something like:
object sumObject;
sumObject = myDataTable.Compute("Sum(Count)", ""); // second parameter is the where clause
For grouping by columns, see this question: Efficient DataTable Group By. It provides a Linq implementation as well as a 'non-Linq' implementation.
Use System.Data.DataSetExtensions and try something like this
var result = from row in dt.AsEnumerable()
group row by row.Field<int>("MakeDistinct") into grp
select new
{
MakeDistinct = grp.Key,
Count = grp.Count()
};

using LINQ to delete specific rows from DataTable

I want to delete a particular row from a DataTable named dt.
For a table in SQL, I could do something like:
DELETE FROM dt
WHERE BASELINE_FOLDER = baselineSubfolder
AND BASELINE_FILE = baselineFilename
AND BASELINE_CHECKSUM = baselineChecksum;
Is there an equivalent LINQ statement for this?
Assuming you don't have the model's and only a DataTable (this is what I understand from the OP).
//Cast to enumerable of `DataRow` and filter on your condition
var rows = dt.Rows.Cast<DataRow>().Where(row => row["BASELINE_FOLDER"] == baselineSubFolder && row["BASELINE_FILE" == baselineFilename
&& row["BASELINE_CHECKSUM"] == baselineChecksum).ToArray();
//Loop through and remove the rows that meet the condition
foreach(DataRow dr in rows)
{
dt.Rows.Remove(dr);
}
you can convert the data table to list and can use RemoveAt() to do so.
You can convert it to list and use the below code
string baseLineFolder=dt.Rows["BASELINE_FOLDER"].ToString();
string baseLineFile=dt.Rows["BASELINE_FILE"].ToString();
string baseLineChecksum=dt.Rows["BASELINE_CHECKSUM"].ToString();
var dtresult = dt.AsEnumerable();
var result=(from r in dtresult
where(r.Field<string>("BASELINE_FOLDER")!=baseLineFolder)
&&(r.Field<string>("BASELINE_FILE")!=baseLineFile)
&&(r.Field<string>("BASELINE_CHECKSUM ")!=baseLineChecksum)
select r).ToList();

Error when Copying Query from linq to Datatable

I just started working on a project that requires Linq to Sql, and I have been able to make queries and retrieve data. But right now I need to fill a DataTable with the data I am retrieving.
My first code was the following:
MyDatabase db = new MyDatabase();
var query = from cust in db.Customers
where cust.CustomerName != "Dante"
orderby cust.CustomerName
select new { Name = cust.CustomerName };
So, since I needed to copy the content of my query to a Datatable I tried this:
IEnumerable<DataRow> query =
from order in orders.AsEnumerable()
where order.Field<DateTime>("OrderDate") > new DateTime(2001, 8, 1)
select order;
// Create a table from the query.
DataTable boundTable = query.CopyToDataTable<DataRow>();
Then, my code looks like this:
IEnumerable<DataRow> myQuery = from cust in db.Customers.AsEnumerable()
where cust.Name != "Dante"
orderby cust.Name
select new { Name = cust.Name };
DataTable myDataTable = myQuery.CopyToDataTable<DataRow>();
But with this code the compiler raises and error:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<System.Data.DataRow>
The error is raised at the select word.
So, What am I doing wrong?? What can I do in order to avoid this conversion issue?
Hope someone can help me, thanks in advance.
There is a way to create a DataTable from a result other than IEnumerable<DataRow>, but it is rather involved. Implement CopyToDataTable Where the Generic Type T Is Not a DataRow.
For your case, though, I would recommend doing it the following way. Go back to your original query:
MyDatabase db = new MyDatabase();
var query = from cust in db.Customers
where cust.CustomerName != "Dante"
orderby cust.CustomerName
select new { Name = cust.CustomerName };
Then define your single field DataTable because when you eventually create a DataRow, it needs a schema to work from:
DataTable myDataTable = new DataTable();
myDataTable.Columns.Add(
new DataColumn()
{
DataType = System.Type.GetType("System.String"),
ColumnName = "Name"
}
);
And finally, go through the results of your query and manually add the DataRows to your DataTable.
foreach (var element in query)
{
var row = myDataTable.NewRow();
row["Name"] = element.Name;
myDataTable.Rows.Add(row);
}
The problem is exactly as the error states; your "select" clause is creating instances of an anonymous type with one member, "Name". This anonymous type is not and cannot be a DataRow, so the implicit conversion between what the query produces and the variable you want to set it into fails.
Instead, you should take this query, and for each element of the anonymous type that it returns, add the value as a new DataRow of the DataTable. You cannot just create a new DataRow from scratch; the DataRow class requires a context, namely the parent DataTable, to define the columns the DataRow should have.
This will do i guess
var myQuery = from cust in db.Customers.AsEnumerable()
where cust.Name != "Dante"
orderby cust.Name
select new { Name = cust.Name };
or try this
string[] myQuery = db.Customers.Rows
.Cast<DataRow>()
.Where(r=>r.Name!="Dante")
.Orderby(r=>r.Name)
.Select(r=>r.Field<string>("Name"))
.ToArray()

Categories

Resources