I know this is obviously a repeated question to ask but I am unable to figure out the issue, as I am new to LINQ.
Basically I have to matchup for duplicate entry of data while adding multiple records at a time. So, I have a Table in my database that has few rows and then I create DataTable dynamically which is clone(in terms of structure) of that table. Now dtDup is the Database Table, returned as dataset/datatable from a select query, and dupVals is the dynamic clone that is to be cross checked for duplicates
var CommnRows =
from dbA in dtDup.AsEnumerable()
join appB in dupVals.AsEnumerable() on
new {
MonthID = dbA.Field<int>("MonthID"),
UserID = dbA.Field<int?>("UserID"), //nullable int
IsActive = dbA.Field<bool?>("IsActive"), //nullable bit
Gender = dbA.Field<String>("Gender").ToString().ToUpper()
}
equals
new {
MonthID = appB.Field<int>("MonthID"),
UserID = appB.Field<int?>("UserID"),
IsActive = appB.Field<bool?>("IsActive")
Gender = appB.Field<String>("Gender").ToString().ToUpper()
}
select dbA;
So, in case I have some rows returned then (I assume, that above join is correct inner join) this means that there are duplicate rows.
But I am getting an error:
Object reference not set to an instance of an object
at new after equals
I found the issue. I was trying to change the type of one of my column that was a string and at first I did not included in the question (now updated), but when I tried debugging it line by line, I found that it was breaking while near Gender. So, just removed the ToString().ToUpper() from that area and it worked.
Related
When i am running query in data base and fill data table with load method first column name coming with table name.column name(Employee.Name,sal,location) rest of the column name coming only column names present in the database.Why table name appending first column name while displaying in data table structure please help me in this regards.
DataTable table = new DataTable();
try
{
using (IDbCommand DbCommand = dbConnection.CreateCommand())
{
DbCommand.CommandText = query;
IDataReader reader = DbCommand.ExecuteReader();
table.Load(reader);
}
}
Sample query Select Employee.Numnber, Employee.salary, Employee.city,dept.deptId from Employee inner join dept where deptiId=EmployeeDeptId
The actual query is :
Select
AP_LINE.LINE_NO, AP_LINE.PRODUCT, AP_LINE.QTY, AP_LINE.REQUESTED_DATE,
AP_LINE.LIST_PRICE, AP_LINE.CONS_NET_MULT,AP_LINE.NETADDERS,
AP_LINE.CONS_NET_PRICE, AP_LINE.Details,TDP_JSP.ID, TDP_JSP.LINE_NO,
TDP_JSP_AppInfo.Id
From AP_LINE, CONFIG, TDP_JSP
inner join TDP_JSP_AppInfo on TDP_JSP.ID= TDP_JSP_AppInfo.ID
where AP_LINE.LINE_NO = TDP_JSP.LINE_NO ;
Out put in data table as coming below
Ap_Line.Line_No,Product,QTY,Requested Date...
There are two LINE_NO columns in the query, AP_LINE.LINE_NO and TDP_JSP.LINE_NO. Columns must have unique names, so DataTable.Load used the two-part name wherever needed. It that wasn't possible it would start appending indexes or even generate names like Column0, Column1 etc.
In this case though, one of those columns isn't needed. The two tables are join those columns. WHERE AP_LINE.LINE_NO = TDP_JSP.LINE_NO is the old-style, frowned-upon join syntax. Those two columns will always have the same data so one of them can be removed.
I am trying to merge data from two separate queries using C#. The data is located on separate servers or I would just combine the queries. I want to update the data in one of the columns of the first data set with the data in one of the columns of the second data set, joining on a different column.
Here is what I have so far:
ds.Tables[3].Columns[2].ReadOnly = false;
List<object> table = new List<object>();
table = ds.Tables[3].AsEnumerable().Select(r => r[2] = reader.AsEnumerable().Where(s => r[3] == s[0])).ToList();
The ToList() is just for debugging. To summarize, ds.Tables[3].Rows[2] is the column I want to update. ds.Tables[3].Rows[3] contains the key I want to join to.
In the reader, the first column contains the matching key to ds.Tables[3].Rows[3] and the second column contains the data with which I want to update ds.Tables[3].Rows[2].
The error I keep getting is
Unable to cast object of type 'WhereEnumerableIterator1[System.Data.IDataRecord]' to type 'System.IConvertible'.Couldn't store <System.Linq.Enumerable+WhereEnumerableIterator1[System.Data.IDataRecord]> in Quoting Dealers Column. Expected type is Int32.
Where am I going wrong with my LINQ?
EDIT:
I updated the line where the updating is happening
table = ds.Tables[3].AsEnumerable().Select(r => r[2] = reader.AsEnumerable().First(s => r[3] == s[0])[1]).ToList();
but now I keep getting
Sequence contains no matching element
For the record, the sequence does contain a matching element.
You can use the following sample to achieve the join and update operation. Let's suppose there are two Datatables:
tbl1:
tbl2:
Joining two tables and updating the value of column "name1" of tbl1 from column "name2" of tbl2.
public DataTable JoinAndUpdate(DataTable tbl1, DataTable tbl2)
{
// for demo purpose I have created a clone of tbl1.
// you can define a custom schema, if needed.
DataTable dtResult = tbl1.Clone();
var result = from dataRows1 in tbl1.AsEnumerable()
join dataRows2 in tbl2.AsEnumerable()
on dataRows1.Field<int>("ID") equals dataRows2.Field<int>("ID") into lj
from reader in lj
select new object[]
{
dataRows1.Field<int>("ID"), // ID from table 1
reader.Field<string>("name2"), // Updated column value from table 2
dataRows1.Field<int>("age")
// .. here comes the rest of the fields from table 1.
};
// Load the results in the table
result.ToList().ForEach(row => dtResult.LoadDataRow(row, false));
return dtResult;
}
Here's the result:
After considering what #DStanley said about LINQ, I abandoned it and went with a foreach statement. See code below:
ds.Tables[3].Columns[2].ReadOnly = false;
while (reader.Read())
{
foreach (DataRow item in ds.Tables[3].Rows)
{
if ((Guid)item[3] == reader.GetGuid(0))
{
item[2] = reader.GetInt32(1);
}
}
}
I have a CheckedListbox which contains values from some table called products.
The idea is to check the products that are associated to a customer. Now it does save correctly in an link table, yet when loading it again, the items that were checked do not get loaded correctly into the CheckedListbox.
So from that link table where, I would like to get all rows from just one column. All tables are already loaded into the application so I don't want to use sql.
I've tried using linq, with no success, Ids is just empty here.
int[] Ids = (from m in dataset.Tables["LinkTable"].AsEnumerable()
where m.Field<int>("customerId") == customerId
select m.Field<int>("productId")).ToArray();
Then, if I do succeed to get those Id's, I would like to get the indexes of those primary keys so I can set the correct products to checked.
I've tired doing it like this, but this gives me error in other parts of the program, because I am setting a Primary key to a global datatable. Datagridviews don't like that.
DataColumn[] keyColumns = new DataColumn[1];
keyColumns[0] = dataset.Tables["products"].Columns["Id"];
currentPatient.GetTheDataSet.Tables["products"].PrimaryKey = keyColumns;
foreach (int Id in Ids)
{
DataRow row = dataset.Tables["Products"].Rows.Find(Id);
int index = dataset.Tables["Products"].Rows.IndexOf(row);
clbMedications.SetItemChecked(index, true);
}
I would like to do that last part without specifying a primary key, I couldn't find how to do that in linq.
I know it consists of 2 questions, but perhaps this can be done with just one linq statement so I better combine them.
[EDIT]
Finally, i think i've got what you need:
var qry = (from p in ds.Tables["products"].AsEnumerable()
select new {
Id = p.Field<int>("Id"),
Index = ds.Tables["products"].Rows.IndexOf(p),
Checked = ds.Tables["LinkTable"].AsEnumerable().Any(x=>x.Field<int>("productId") == p.Field<int>("Id") && x.Field<int>("customerId")==customerid)
}).ToList();
Above query returns the list, which you can bnid with CheckedListbox.
I previously asked the question and got answer to Best approach to write query but the problem is that if you have to save this result in a list then there duplication of records. For example
the resultant table of the join given EXAMPLE
See there are duplicate rows. How can you filter them out, and yet save the data of order number?
Of course there may be some ways but I am looking for some great ways
How can we store the data in list and not create duplicate rows in list?
My current code for my tables is
int lastUserId = 0;
sql_cmd = new SqlCommand();
sql_cmd.Connection = sql_con;
sql_cmd.CommandText = "SELECT * FROM AccountsUsers LEFT JOIN Accounts ON AccountsUsers.Id = Accounts.userId ORDER BY AccountsUsers.accFirstName";
SqlDataReader reader = sql_cmd.ExecuteReader();
if (reader.HasRows == true)
{
Users userToAdd = new Users();
while (reader.Read())
{
userToAdd = new Users();
userToAdd.userId = int.Parse(reader["Id"].ToString());
userToAdd.firstName = reader["accFirstName"].ToString();
userToAdd.lastName = reader["accLastName"].ToString();
lastUserId = userToAdd.userId;
Websites domainData = new Websites();
domainData.domainName = reader["accDomainName"].ToString();
domainData.userName = reader["accUserName"].ToString();
domainData.password = reader["accPass"].ToString();
domainData.URL = reader["accDomain"].ToString();
userToAdd.DomainData.Add(domainData);
allUsers.Add(userToAdd);
}
}
For second table I have custom list that will hold the entries of all the data in second table.
The table returned is table having joins and have multiple rows for same
Besides using the Dictionary idea as answered by Antonio Bakula...
If you persist the dictionary of users and call the code in your sample multiple times you should consider that a user account is either new, modifed, or deleted.
The algorithm to use is the following when executing your SQL query:
If row in query result is not in dictionary create and add new user to the dictionary.
If row in query result is in dictionary update the user information.
If dictionary item not in query result delete the user from the dictionary.
I'd also recommend not using SELECT *
Use only the table columns your code needs, this improves the performance of your code, and prevents a potential security breach by returning private user information.
i am not sure why are you not using distinct clause in your sql to fetch unique results. also that will be faster. did you look at using hashtables.
I would put users into Dictonary and check if allready exists, something like this :
Dictionary<int, Users> allUsers = new Dictionary<int, Users>()
and then in Reader while loop :
int userId = int.Parse(reader["Id"].ToString());
Users currUser = allUsers[userId];
if (currUser == null)
{
currUser = new Users();
currUser.userId = userId);
currUser.firstName = reader["accFirstName"].ToString();
currUser.lastName = reader["accLastName"].ToString();
allUsers.Add(userID, currUser);
}
Websites domainData = new Websites();
domainData.domainName = reader["accDomainName"].ToString();
domainData.userName = reader["accUserName"].ToString();
domainData.password = reader["accPass"].ToString();
domainData.URL = reader["accDomain"].ToString();
currUser.DomainData.Add(domainData);
Seems like the root of your problem is in your database table.
When you said duplicate data rows, are you saying you get duplicate entries in the list or you have duplicate data in your table?
Give 2 rows that are duplicate.
Two options:
First, prevent pulling duplicate data from sql by using a distinct clause like:
select distinct from where
Second option as mentioned Antonio, is to check if the list already has it.
First option is recommended unless there are other reasons.
I'm creating a method that populates some textboxes with data retrieved from an Access database using table adapters.
The GetCasesWithUserFromCaseId method return a single case with the username which is found by left joining my cases table with my users table.
For some reason I get a NullReferenceException when trying to access the joined data (userdata) from the users table but data from the cases table works. I'm sure that all fields is set for all users and all cases-tablerows.
If this doesn't work how do I then alternately get my data? I've attached an image showing my simple database.
The sql-statement:
SELECT *
FROM cases
LEFT JOIN users ON cases.caseCreatedBy = users.userId
WHERE caseId = caseNum
The C# code:
public void populateBoxes(int caseId)
{
caseDBTableAdapters.casesTableAdapter casesAdapter =
new caseDBTableAdapters.casesTableAdapter();
caseDB.casesDataTable cases;
cases = casesAdapter.GetCasesWithUserFromCaseId(caseId);
foreach (caseDB.casesRow casesRow in cases)
{
tbCaseName.Text = casesRow.caseName;
tbOwner.Text = casesRow.usersRow.firstName.ToString();
}
}
Well, the point is: if you do a LEFT OUTER JOIN on your Users table, then this statement here is dangerous:
foreach (caseDB.casesRow casesRow in cases)
{
tbCaseName.Text = casesRow.caseName;
tbOwner.Text = casesRow.usersRow.firstName.ToString(); <== !!!!!
}
With a LEFT OUTER JOIN, there's a chance that there are no users for your case - so casesRow.usersRow would be null.
You need to check for that!
foreach (caseDB.casesRow casesRow in cases)
{
tbCaseName.Text = casesRow.caseName;
if(casesRow.usersRow != null)
{
tbOwner.Text = casesRow.usersRow.firstName.ToString();
}
}
You mentioned that the GetCasesWithUserFromCaseId() method is joining the cases and users tables with a left join. Is the exemption you are getting a NullReferenceExemption?
I would guess that the output of your access method is resulting in
caseName firstName
---------- ----------
Bildsoe NULL
if that is the case, then in your code line:
tbOwner.Text = casesRow.usersRow.firstName.ToString();
the usersRow property of the casesRow is likely to be null. You will have to check if the property is null before you try to reference it.