P
Pat Pattillo
Hi,
I am doing a 3 tier thick client app and use a middle tier to get and put
dataset contents. I am using an approach, very similar to many prescribed by
Microsoft and in books to create a pseudokey as an identity/autoincrement
column with seed and step both -1. Then when database table is updated, the
stored procedure that ultimately updates returns the true key via
SCOPE_IDENTITY().
The problem does not seem to involve the database at all, or in any case,
directly.
Here is the Microsoft example:
DataSet ds = new DataSet();
try
{
//Fill DataSet, and then set DataRelation to move through
the DataGrid.
conn.Open();
daOrder.FillSchema(ds,SchemaType.Mapped,"Orders");
daOrder.Fill(ds,"Orders");
daDetails.FillSchema(ds,SchemaType.Mapped,"Details");
daDetails.Fill(ds,"Details");
ds.Relations.Add("OrdDetail",
ds.Tables["Orders"].Columns["OrderID"],
ds.Tables["Details"].Columns["OrderID"]);
DataColumn dc = ds.Tables["Orders"].Columns["OrderID"];
dc.AutoIncrement = true;
dc.AutoIncrementSeed = -1;
dc.AutoIncrementStep = -1;
}
catch(SqlException ex)
{
Console.Write (ex.Message.ToString ());
Console.Write(ex.InnerException.ToString ());
}
I think I am doing approximately the same thing but I am not using
FillSchema but rather MissingSchemaAction = AddWithKey...
My problem is that despite my having specified seed and step of -1 after
filling the DataSet, when I add a new row to a DataSet table it attempts to
use a new key that is already in the table, thus violating the primary key
constraint.
Here is my code to fill the DataSet:
DataSet theDataSet = new DataSet(Name);
message = null;
try
{
SqlDataAdapter da = new SqlDataAdapter(SelectCommand());
// could cache schema and use it if available and not expired vs. adding
each time
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
for (int i = 0; i < Tables.Length; i++)
{
string tablename = "Table" + i.ToString();
if (tablename == "Table0") tablename = "Table";
da.TableMappings.Add(Tables, tablename);
}
theDataSet.EnforceConstraints = false;
da.Fill(theDataSet);
int numrelations = Relations.GetLength(0);
for (int i = 0; i < numrelations; i++)
{
theDataSet.Relations.Add(Tables[i+1], theDataSet.Tables[Relations[i,
0]].Columns[Relations[i, 1]], theDataSet.Tables[Relations[i,
2]].Columns[Relations[i, 3]]);
}
for (int i = 0; i < Tables.Length; i++)
{
// NOTE : This assumes that all primary keys are identity
DataColumn dc = theDataSet.Tables[0].PrimaryKey[0];
theDataSet.Tables.Columns["pk"].AutoIncrement = true;
theDataSet.Tables.Columns["pk"].AutoIncrementSeed = -1;
theDataSet.Tables.Columns["pk"].AutoIncrementStep = -1;
theDataSet.Tables.Columns["pk"].ReadOnly = true;
}
theDataSet.EnforceConstraints = true;
}
catch(System.Exception ex)
{
theDataSet = null;
message = ex.Message;
}
Finally when the fill routine returns the following code is executed to add
a new row:
DataColumn dc = ds.Tables["Table"].Columns["pk"];
DataRow row = ds.Tables[0].NewRow();
row["f1"] = "f1";
row["f2"] = "f2";
ds.Tables[0].Rows.Add(row);
The last statement incurs the primary constraint error but examination of
the row after the execution of NewRow() reveals that a row with a positive
primary key value is being created, the value already being a key of a row
that is already in both the table and the database.
Any ideas? Anyone? I am stumped, and all ears. I may try some things in the
meantime but if I find anything I'll reply to this post myself.
Thanks for any help!!! Really!!! I must be missing something either
incredibly obvious or incredibly subtle.
I am doing a 3 tier thick client app and use a middle tier to get and put
dataset contents. I am using an approach, very similar to many prescribed by
Microsoft and in books to create a pseudokey as an identity/autoincrement
column with seed and step both -1. Then when database table is updated, the
stored procedure that ultimately updates returns the true key via
SCOPE_IDENTITY().
The problem does not seem to involve the database at all, or in any case,
directly.
Here is the Microsoft example:
DataSet ds = new DataSet();
try
{
//Fill DataSet, and then set DataRelation to move through
the DataGrid.
conn.Open();
daOrder.FillSchema(ds,SchemaType.Mapped,"Orders");
daOrder.Fill(ds,"Orders");
daDetails.FillSchema(ds,SchemaType.Mapped,"Details");
daDetails.Fill(ds,"Details");
ds.Relations.Add("OrdDetail",
ds.Tables["Orders"].Columns["OrderID"],
ds.Tables["Details"].Columns["OrderID"]);
DataColumn dc = ds.Tables["Orders"].Columns["OrderID"];
dc.AutoIncrement = true;
dc.AutoIncrementSeed = -1;
dc.AutoIncrementStep = -1;
}
catch(SqlException ex)
{
Console.Write (ex.Message.ToString ());
Console.Write(ex.InnerException.ToString ());
}
I think I am doing approximately the same thing but I am not using
FillSchema but rather MissingSchemaAction = AddWithKey...
My problem is that despite my having specified seed and step of -1 after
filling the DataSet, when I add a new row to a DataSet table it attempts to
use a new key that is already in the table, thus violating the primary key
constraint.
Here is my code to fill the DataSet:
DataSet theDataSet = new DataSet(Name);
message = null;
try
{
SqlDataAdapter da = new SqlDataAdapter(SelectCommand());
// could cache schema and use it if available and not expired vs. adding
each time
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
for (int i = 0; i < Tables.Length; i++)
{
string tablename = "Table" + i.ToString();
if (tablename == "Table0") tablename = "Table";
da.TableMappings.Add(Tables, tablename);
}
theDataSet.EnforceConstraints = false;
da.Fill(theDataSet);
int numrelations = Relations.GetLength(0);
for (int i = 0; i < numrelations; i++)
{
theDataSet.Relations.Add(Tables[i+1], theDataSet.Tables[Relations[i,
0]].Columns[Relations[i, 1]], theDataSet.Tables[Relations[i,
2]].Columns[Relations[i, 3]]);
}
for (int i = 0; i < Tables.Length; i++)
{
// NOTE : This assumes that all primary keys are identity
DataColumn dc = theDataSet.Tables[0].PrimaryKey[0];
theDataSet.Tables.Columns["pk"].AutoIncrement = true;
theDataSet.Tables.Columns["pk"].AutoIncrementSeed = -1;
theDataSet.Tables.Columns["pk"].AutoIncrementStep = -1;
theDataSet.Tables.Columns["pk"].ReadOnly = true;
}
theDataSet.EnforceConstraints = true;
}
catch(System.Exception ex)
{
theDataSet = null;
message = ex.Message;
}
Finally when the fill routine returns the following code is executed to add
a new row:
DataColumn dc = ds.Tables["Table"].Columns["pk"];
DataRow row = ds.Tables[0].NewRow();
row["f1"] = "f1";
row["f2"] = "f2";
ds.Tables[0].Rows.Add(row);
The last statement incurs the primary constraint error but examination of
the row after the execution of NewRow() reveals that a row with a positive
primary key value is being created, the value already being a key of a row
that is already in both the table and the database.
Any ideas? Anyone? I am stumped, and all ears. I may try some things in the
meantime but if I find anything I'll reply to this post myself.
Thanks for any help!!! Really!!! I must be missing something either
incredibly obvious or incredibly subtle.