UNIQUE constraint on DataTable - c#

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

Related

How to add new column to DataTable with auto index of row (C#)

I have a Datatable, and I need to add "id" or "index" column with auto value.
like a identity column in sql.
I have a function that return me the start index: GetID();
I need that the value of this column in the first row will be the value that GetID() return, the value in the second row will be GetID() + 1.... GetID() + 2 ...
I need to do this without loops .
I thought to use "Expression" when I create new column, but I dont know how to do this.
You can use AutoIncrement property of DataTable column:
var dt = new DataTable();
var col = dt.Columns.Add("ID", typeof (long));
col.AutoIncrement = true;
col.AutoIncrementSeed = GetID();
col.AutoIncrementStep = 1;
But it will work only for rows being added to your DataTable after adding this column.
If you adding this identity column to the DataTable with existed rows - this will not update existed rows, so in this case you're still need loop over your existed rows and update them manually.

Update the dataset after rows changed

Scenario:
Excel file is read and displayed in datagrid.
Values in sql server must be updated if excel values are different.
Table in Sql server don't have primary key
After all these steps, when I am about to update the table, it throws the error saying "Update requires a valid UpdateCommand when passed DataRow collection with modified rows."
There is no primary key. So I need to use update command. BUt how and what would be in update command? importdata is dictionary where data from excel are stored. PLz help!!! What should I do now? I have No idea....
foreach (DataColumn column in ds.Tables[0].Columns)
{
string fieldName = column.ColumnName;
string fieldNameValueE = string.Empty;
if (importdata.ContainsKey(fieldName))
{
fieldNameValueE = importdata[fieldName];
foreach (DataRow dr in ds.Tables[0].Rows)
{
string fieldNameValueD = dr[fieldName].ToString();
if (fieldNameValueD != fieldNameValueE)
{
dr[fieldName] = fieldNameValueE;
}
}
}
}
da.Update(ds);
connection.Close();
So, let's say we were dealing with a table that had a primary key:
CREATE TABLE TableA
{
FieldA INT PRIMARY KEY IDENTITY(1, 1),
FieldB VARCHAR(256) NULL,
FieldC VARCHAR(256) NOT NULL,
}
If you were to use the SqlCommandBuilder (which you cannot because you don't have a primary key), it would build a statement a bit like this:
UPDATE TableA
SET FieldB = #p1,
FieldC = #p2
WHERE (FieldA = #p3 AND
((FieldB IS NULL AND #p4 IS NULL) OR (FieldB = #p5)) AND
FieldC = #p6)
So, you're going to need to build an UPDATE statement that's very similar to do it the way they do. But one thing you need to remember is it's not just the statement, you also have to add all of the parameters to the command that you build - and that's going to become pretty cumbersome.
So, I have two recommendations for you:
Make a primary key on the table.
Issue an ExecuteNonQuery in every iteration of the loop.
The second recommendation would look like this:
foreach (DataColumn column in ds.Tables[0].Columns)
{
string fieldName = column.ColumnName;
string fieldNameValueE = string.Empty;
if (importdata.ContainsKey(fieldName))
{
fieldNameValueE = importdata[fieldName];
foreach (DataRow dr in ds.Tables[0].Rows)
{
string fieldNameValueD = dr[fieldName].ToString();
if (fieldNameValueD != fieldNameValueE)
{
dr[fieldName] = fieldNameValueE;
}
var cmd = new SqlCommand(string.Format(
"UPDATE importdata SET {0} = {1} WHERE fielda = #fielda AND fieldb = #fieldb ...",
fieldName, fieldNameValueE), connectionObject);
cmd.Parameters.AddWithValue(#fielda, dr["fielda", DataRowVersion.Original]);
cmd.Parameters.AddWithValue(#fieldb, dr["fieldb", DataRowVersion.Original]);
cmd.ExecuteNonQuery();
}
}
}
Use SqlCommandBuilder.
After setting up your DataAdapter, initialize a command builder.
Then use the SqlCommandBuilder update feature.
SqlCommandBuilder cb = new SqlCommandBuilder(da);
//Do your other work updating the data
cb.DataAdapter.Update(ds);
That should do the trick!
Edit:
As BigM pointed out, your table needs to have a primary key for the SqlCommandBuilder to work. If however, you can't modify the actual SQL table and mark one of the fields as a Primary Key and you also know that one of the fields is unique, you can add a Primary Key to your DataSet table like this:
DataColumn[] pk1 = new DataColumn[1];
pk1[0] = ds.Tables["TableName"].Columns[0];
ds.Tables["TableName"].PrimaryKey = pk1;
This gives your "in memory" table a primary key so that the SqlCommandBuilder can do its work.
Warning:
You must be sure that the values in the column you mark as primary key are actually unique.

datatable select rows

I am using a datatable created by program. In this datatable i want to insert values in some specified columns.
Initially I am inserting primary key values leaving remaining columns null, when I am querying datatable with recently inserted value in Primary column to update same row, I am facing error Missing operand after ID operator
Can any one tell me the exact issue.
I am trying following code:
dt.Rows.Add(1);
int insertedValue = 1;
DataRow[] dr = dt.Select("ID = '" + insertedValue.toString() + "'");
And the table structure after entring primary value is as follows.
ID Volumn1 Volumn2 volumn3
--------------------------------------
1
You can do this more cleanly with LINQ and make this a strongly typed operation.
Something like:
dt.Rows.Add(1);
int insertedValue = 1;
var result =
dt.AsEnumerable().Where( dr => dr.Field<int>( "ID" ) == insertedValue );
Working example:
DataTable dt = new DataTable();
dt.Columns.Add( "ID", typeof( int ) );
dt.Rows.Add( 1 );
var result = dt.AsEnumerable().Where( dr => dr.Field<int>( "ID" ) == 1 );
You can simply format the selection string as shown below:
DataRow[] dr = dt.Select(string.Format("ID ='{0}' ", insertedValue));
Feel free to let me know if this works for you.. Thanks
You do not need ' ' in your filter.
I think this should work:
DataRow[] dr = dt.Select("ID = " + insertedValue.toString());
By the way, reference System.Data.DataSetExtensions
If you are looking for a specific row and your datatable has a primary key you could use the Find method and target the primary key which would return just the row you want rather than an array:
DataRow foundRow = dt.Rows.Find([INSERT SEARCH PARAMETER HERE]);
if(foundRow != null)
{
TO SET A STRING EQUAL TO A FOUND VALUE:
string str = foundRow["COLUMN NAME / INDEX];
OR IF YOU ARE INSERTING A VALUE YOU CAN USE IT LIKE THIS:
foundRow["COLUMN NAME / INDEX"] = NEW VALUE;
}
select column of row
dt.Rows[0].Field<string>("MyColumnName")

How to check if DataTable contains DataRow?

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")

How to add datarows to an already existing datatable?

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);

Categories

Resources