I have a non-typed dataset filled with data from user input (no database). There's no primary key column (my data had no need for primary key so far)! Is there any way to avoid "brute force" if i want to check if new row user is trying to insert already exists in my DataTable? How should i perform that check?
You can manually create unique constraints for your DataTable:
DataTable custTable = custDS.Tables["Customers"];
UniqueConstraint custUnique = new UniqueConstraint(new DataColumn[]
{custTable.Columns["CustomerID"],
custTable.Columns["CompanyName"]});
custDS.Tables["Customers"].Constraints.Add(custUnique);
For this example, you would get an exception (of type ConstraintException) if you tried to add a row to the table where the CustomerID and CompanyName were duplicates of another row with the same CustomerID and CompanyName.
I would just let the DataTable check these things for you internally - no point reinventing the wheel. As to how it does it (whether it is efficient or not), will have to be an exercise for you.
What you can do is use a DataView. Dataview allow you to use a where clause with the DataView's data.
Check it that way.
To check for any duplicates try
if (table.Rows.Contain(PriKeyTypeValue)) /*See if a Primary Key Value is in
the table already */
continue;
else
table.Row.Add(value1, value2, value3);
If you want to be able to insert duplicate rows but do not want to have an exception thrown set-up your primary key as a unique self-incrementing int then you can insert as many duplicates as you feel like without having to check to see if the table contains that value.you can set primary key value like the below....
DataTable table = new DataTable();
table.Columns.Add("Column", typeof(int));
DataColumn column = table.Columns["Column"];
column.Unique = true;
column.AutoIncrement = true;
column.AutoIncrementStep = 1; //change these to whatever works for you
column.AutoIncrementSeed = 1;
table.PrimaryKey = new DataColumn[] { column };
Much, much easier way:
datatable.Columns.Contais("ColumnName")
Related
What would be the right way to avoid duplication when querying datatable and then saving it to DataTable. I'm using the pattern below, which gets very error-prone once tables grow. I looked at below hints. With first one copyToDataTable() looks not really applicable and second is for me much too complex for the task. I would like to split the below code into 2 separate methods (first to build the query and second to retrieve the DataTable). Perhaps if I avoid the anonymous type in the query this should be easier to avoid hardcoding all the column names - but I'm somehow lost with this.
Filling a DataSet or DataTable from a LINQ query result set
or
https://msdn.microsoft.com/en-us/library/bb669096%28v=vs.110%29.aspx
public DataTable retrieveReadyReadingDataTable()
{
DataTable dtblReadyToSaveToDb = RetrieveDataTableExConstraints();
var query = from scr in scrTable.AsEnumerable()
from products in productsTable.AsEnumerable()
where(scr.Field<string>("EAN") == products.Field<string>("EAN"))
select
new
{
Date = DateTime.Today.Date,
ProductId = products.Field<string>("SkuCode"),
Distributor = scr.Field<string>("Distributor"),
Price = float.Parse(scr.Field<string>("Price")),
Url = scr.Field<string>("Url")
};
foreach (var q in query)
{
DataRow newRow = dtblReadyToSaveToDb.Rows.Add();
newRow.SetField("Date", q.Date);
newRow.SetField("ProductId", q.ProductId);
newRow.SetField("Distributor", q.Distributor);
newRow.SetField("Price", q.Price);
newRow.SetField("Url", q.Url);
}
return dtblReadyToSaveToDb;
}
Firstly, you have to decide what "duplicate" means in your case. According to your code i would say a duplicate is a row with the same value in column Date, ProductId and Distributor. So add a multi column primary key for those columns first.
Secondly, you should add some sort of code that first queries existing rows and then compares these existing rows to the rows you want to create. If a match is found, then simply just don't insert a new row.
I am using a DataTable and SqlBulkCopy to insert data into a SQL Server database table.
I have managed to bulk insert the rows using the following settings but only using negative values as otherwise I get conflicts as the value is not unique:
DataTable table = new DataTable();
DataColumn column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.AutoIncrement = true;
column.AutoIncrementSeed = 0;
column.AutoIncrementStep = -1;
table.Columns.Add(column);
table.Columns.Add(DB_Base.DBTable_Start, typeof(DateTime));
I have a loop that generates rows to be inserted like this:
table.Rows.Add(null,tsoOptions.start);
I then set the table and connection and write the data using the WriteToServer() method. This is all working fine and the rows appear but with negative autoincrement primary keys.
How do I modify this so that it will append the rows with a positive value which continues after the last (MAX) value without reading the max value in a separate query?
Assuming your table in the database is created properly with the column auto-increment (i.e. IDENTITY) turned on, don't duplicate this functionality in your code. Just send the records to the database with the null value for that column and the database will do its job. Comment out these lines and try:
//column.AutoIncrement = true;
//column.AutoIncrementSeed = 0;
//column.AutoIncrementStep = -1;
UPDATE
Actually the best way to do it is by not mapping the identity column at all, so comment out all these lines:
//DataColumn column = new DataColumn();
//column.DataType = System.Type.GetType("System.Int32");
//column.AutoIncrement = true;
//column.AutoIncrementSeed = 0;
//column.AutoIncrementStep = -1;
//table.Columns.Add(column);
//table.Columns.Add(DB_Base.DBTable_Start, typeof(DateTime));
And make sure you're not using SqlBulkCopyOptions.KeepIdentity (check this).
Do you need to setup this in the DataTable object? Usually I'd go on SSMS (Sql Server Management Studio) and set up the primary key as Identity and Increment to one.
When I save in the database, I just don't send anything for this column:
1) Right-click on the table in SSMS tree on the left, choose design
2) Click on your primary-key column and have a look on Column Properties section, you should set up like this:
That should do the job!
UPDATE: Like the other guy here suggested, comment out the lines of your code that you are trying to set up seed and identity and do this in SSMS instead.
var sdr = db.ExecuteReader("SELECT [key],translation FROM language WHERE lang=#lang");
DataTable someTable = new DataTable();
someTable.Load(sdr);
return ((string)(someTable.Rows.Find("[key] = CUSTOMDATEFORMAT").ItemArray[1]));
The last line now throws the error System.Data.MissingPrimaryKeyException: "The table has no primary key."
So I guess it finds the keyword "key" and now expects me to query on the primary key column, not the column named "key". How do I have to escape the column name?
If you want to use DataRowCollection.Find you have to specify the DataTable's PrimaryKey(s).
I would use Linq-To-DataTable:
DataRow row = someTable.AsEnumerable()
.FirstOrDefault(row => row.Field<string>("key") == "CUSTOMDATEFORMAT");
if(row != null)
return row.Field<string>(1); // or by name but with correct type
else
return "something else";
Then you can use all methods you want in the query.
The Find method is used to find a single rows by the primary key value. Use Select to find rows by arbitrary column values:
DataRow[] foundRows;
foundRows = someTable.Select("[key] = CUSTOMDATEFORMAT");
return foundRows[0].ItemArray[1]; // adding proper bounds checking, of course.
Find method is using the column that is specified in the DataTable object as primary key and return a row that contains the value it gets inside the primary key cell.
From MSDN:
Gets the row specified by the primary key value.
Since your table doesn't have a column that is specified as a primary key, you get this error.
If your key column is guaranteed to not contain duplicates, you can specify it as the primary key using the DataTable's PrimaryKey property.
If not, then use Linq's Select method instead of find:
return ((string)(someTable.Rows.Select("[key] = CUSTOMDATEFORMAT").ItemArray[1]));
Can I have a clustered key on DataTable in C# ?
There's a requirement in my code to have constraints for possible combinations of 3 columns to be unique .....
What you need is really a unique constraint on your DataTable. Clustered keys are a SQL Server on-disk feature and not applicable to a DataTable.
Check out MSDN doc on DataTable constraints:
The UniqueConstraint object, which can be assigned either to a single column or to an array of columns in a DataTable, ensures that all data in the specified column or columns is unique per row. You can create a unique constraint for a column or array of columns by using the UniqueConstraint constructor.
So try something like this:
// this is your DataTable
DataTable custTable ;
// create a UniqueConstraint instance and set its columns that should make up
// that uniqueness constraint - in your case, that would be a set of *three*
// columns, obviously! Adapt to your needs!
UniqueConstraint custUnique =
new UniqueConstraint(new DataColumn[] { custTable.Columns["CustomerID"],
custTable.Columns["CompanyName"] });
// add unique constraint to the list of constraints for your DataTable
custTable.Constraints.Add(custUnique);
And that should do the trick for you!
To make your columns enforce a UNIQUE constraint you could use
DataTable dt = new DataTable();
dt.Columns.Add("UniqueColumn");
dt.Columns["UniqueColumn"].Unique = true;
Solution two
If you want some combination of the values in some columns to have unique value, you can try this.
DataTable dt = new DataTable();
dt.Columns.Add("UniqueColumn1");
dt.Columns.Add("UniqueColumn2");
dt.Columns.Add("UniqueColumn3");
dt.Columns.Add("NormalColumn");
string
value1 = string.Empty,
value2 = string.Empty,
value3 = string.Empty,
value4 = string.Empty;
//Logic to take values in string values variables goes here
DataRow[] founded = dt.Select("UniqueColumn1 = '"+ value1+
"' and UniqueColumn2 = '"+value2+
"' and UniqueColumn3 = '"+value3+"'");
if (founded.Length > 0)
// Message to say values already exist.
else
// Add a new row to your dt.
In this code you check the data present in DT to enforce uniqueness
I am having an datatable which is already populated. Now i want to add few rows to that datatable ,but some of rows might already exist in the datatable.I know its unneccesary but tht is the requirement.
I tried couple of things and got "the row already exist in this table : & this row belongs to some other table" .I also tried importRow ,but i guess it avoid the duplicates by dafault.
Is there any way to do that .If the datatable has 7 rows and i want to add 3 more rows whether its already exist or not. My goal is to send 10 rows to the calling function .
Or is there any other approach altogether?
UPDATE
Using
rowsToAdd.CopyToDataTable(dsCount.Tables[2], LoadOption.PreserveChanges); works but I'm not sure it's the proper way.
You can add new rows in DataTable using code below
DataRow newRow = dataTable.NewRow();
dataTable.Rows.Add(newRow);
To check for any duplicates try
if (table.Rows.Contain(PriKeyTypeValue)) /*See if a Primary Key Value is in
the table already */
continue;
else
table.Row.Add(value1, value2, value3);
If you want to be able to insert duplicate rows but do not want to have an exception thrown set-up your primary key as a unique self-incrementing int then you can insert as many duplicates as you feel like without having to check to see if the table contains that value. Just make sure that it would suffice to have duplicates. There are plenty of examples of setting a primary key just search for it (msdn has at least one). Here is an example:
DataTable table = new DataTable();
table.Columns.Add("Column", typeof(int));
DataColumn column = table.Columns["Column"];
column.Unique = true;
column.AutoIncrement = true;
column.AutoIncrementStep = 1; //change these to whatever works for you
column.AutoIncrementSeed = 1;
table.PrimaryKey = new DataColumn[] { column };
Create a new row using the NewRow() function.
var dataTable = new DataTable();
var dataRow = dataTable.NewRow();
Then add your new row to your datatable
dataTable.Rows.Add(dataRow)
I believe you can use the NewRow() function of the DataTable if you're simply appending a row to the table.
DataTable table = new DataTable();
DataRow row = table.NewRow();
table.Rows.Add(row);
Will that not suffice?
The most straightforward method. After spending a few hours trying everything else.
DataRow dr = ds.Tables[0].NewRow();
dr["ColumnName1"] = "columnvalue"; //string
dr["ColumnName2"] = 123 //int
ds.Tables[0].Rows.Add(dr);