[英]Delete row - generated sql is not supported for multiple table
I am joining tables in my command. 我在命令中加入表格。 I would like to delete the current row.
我想删除当前行。
Below is my command and what I usually do. 以下是我的命令以及通常执行的操作。
But today I have the error: 但是今天我有错误:
generated sql is not supported for multiple table delete row
多表删除行不支持生成的sql
What does that mean?? 这意味着什么??
OleDbCommand mycmdL = new OleDbCommand("SELECT DISTINCT AreaSize.*, Bathrooms.*, Cities.*, Prices.*, Properties.*, Rooms.*, Types.*, Users.* FROM Users INNER JOIN (Types INNER JOIN (Rooms INNER JOIN (Prices INNER JOIN (Cities INNER JOIN (Bathrooms INNER JOIN (AreaSize INNER JOIN Properties ON AreaSize.AreaSizeID = Properties.AreaSize) ON Bathrooms.BathroomID = Properties.Bathrooms) ON Cities.CityID = Properties.City) ON Prices.PriceID = Properties.Price) ON Rooms.RoomID = Properties.Rooms) ON Types.TypeID = Properties.PropertyType) ON Users.UserID = Properties.AgentID WHERE Users.UserID =@userID", clsDataSource.mycon);
myadaptL = new OleDbDataAdapter(mycmdL);
myadaptL.Fill(clsDataSource.myset, "Properties");
tbListing = clsDataSource.myset.Tables["Properties"];
Code to delete current row: 删除当前行的代码:
try
{
if (MessageBox.Show("Are you sure?", "??", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
DataRow myrow = tbListing.Rows[current];
myrow.Delete();
OleDbCommandBuilder mybuild = new OleDbCommandBuilder(myadaptL);
myadaptL.Update(tbListing);
}
}
catch (Exception)
{
throw;
}
}
But today I have the error:
但是今天我有错误:
generated sql is not supported for multiple table delete row
What does that mean??
这意味着什么??
As the error message says, the DbCommandBuilder
can only auto-generate SQL for single table queries. 如错误消息所述,
DbCommandBuilder
只能为单表查询自动生成SQL。 This makes it easy to implement apps maintaining base tables such as Customer, Product, Employee etc. They can be used for something like a Customer-Order-OrderLines-ServiceItem
relationship, but you have to go about it differently. 这样可以轻松实现维护基本表(例如客户,产品,员工等)的应用程序。它们可以用于诸如
Customer-Order-OrderLines-ServiceItem
关系之类的东西,但是您必须进行不同的处理。
But before you do that know that there are various frameworks out there to help implement and manage this kind of thing for you. 但是在您这样做之前,请先知道有各种框架可以帮助您实现和管理这种事情。 Look into ORMs.
查看ORM。
Since the DataAdapter
can only update one table at a time, you will need multiple Adapters. 由于
DataAdapter
一次只能更新一个表,因此您将需要多个适配器。 Rather than using a SQL JOIN, you can define the PK-FK relationship. 您可以定义PK-FK关系,而不是使用SQL JOIN。 Changes to parent rows will cascade to children.
对父级行的更改将级联到子级。
For demo purposes I have tables cleverly names Parent
, Child
and SubChild
. 出于演示目的,我巧妙地将表命名为
Parent
, Child
和SubChild
。 A parent row can have many child rows (1:m); 父行可以有许多子行(1:m); each child can have many subchild rows (1:m).
每个孩子可以有许多子孩子行(1:m)。
// form/class level objects
DataSet dsSample;
OleDbDataAdapter daParent;
OleDbDataAdapter daChild;
OleDbDataAdapter daSubCh;
Elsewhere, configure them: 在其他地方,配置它们:
daParent = new OleDbDataAdapter("SELECT Id, Name, Lorem FROM Parent",
AceConnStr);
dsSample.Tables.Add("Parent");
var cbP = new OleDbCommandBuilder(daParent);
daParent.UpdateCommand = cbP.GetUpdateCommand();
daParent.InsertCommand = cbP.GetInsertCommand();
daParent.FillSchema(dsSample.Tables["Parent"], SchemaType.Source);
daParent.Fill(dsSample.Tables["Parent"]);
// repeat for Child - use care with copy-paste!
daChild = new OleDbDataAdapter("SELECT Id, ParentId, Name, Lorem FROM Child",
AceConnStr);
dsSample.Tables.Add("Child");
var cbS = new OleDbCommandBuilder(daChild);
daChild.UpdateCommand = cbS.GetUpdateCommand();
daChild.InsertCommand = cbS.GetInsertCommand();
daChild.FillSchema(dsSample.Tables["Child"], SchemaType.Source);
daChild.Fill(dsSample.Tables["Child"]);
// do the same for the subchild adapter
// omitted for brevity
// ...
// the PK cols
DataColumn colParent = dsSample.Tables["Parent"].Columns["Id"];
DataColumn colChild = dsSample.Tables["Child"].Columns["Id"];
// set FK constraints, rules
ForeignKeyConstraint fkParentChild = new ForeignKeyConstraint("ParentChild",
colParent,
dsSample.Tables["Child"].Columns["ParentId"]);
fkParentChild.DeleteRule = Rule.Cascade;
fkParentChild.UpdateRule = Rule.Cascade;
fkParentChild.AcceptRejectRule = AcceptRejectRule.Cascade;
dsSample.Tables["Child"].Constraints.Add(fkParentChild);
// set FK constraints, rules for Child-SubChild
ForeignKeyConstraint fkChildSub = new ForeignKeyConstraint("ChildSub",
colChild,
dsSample.Tables["SubChild"].Columns["ChildId"]);
fkChildSub.DeleteRule = Rule.Cascade;
fkChildSub.UpdateRule = Rule.Cascade;
fkChildSub.AcceptRejectRule = AcceptRejectRule.Cascade;
dsSample.Tables["SubChild"].Constraints.Add(fkChildSub);
dsSample.EnforceConstraints = true;
When a Parent row is deleted the related child rows will be affected; 当父行被删除时,相关的子行将受到影响; same for Child-to-SubChild.
子对子子相同。 Note that even if you do not opt for some sort of ORM, lots of this can be broken up and handled by classes related to the actor.
请注意,即使您不选择某种ORM,也可以通过与actor相关的类来分解和处理其中的许多内容。 For instance, a
Room
or City
class handling that bit of data. 例如,一个
Room
或City
类处理该数据位。
Testing the Relationship(s) 测试关系
A query for the rows related to "ParentB": 查询与“ ParentB”相关的行:
ChildB1
is the first child row for ParentB; ChildB1
是ChildB1
的第一子行; ChildB-1C
means the subchild is related to the First childrow related to parentB. ChildB-1C
表示子孩子与与parentB有关的第一个子行有关。 That didnt turn out as clear as I thought it would. Test: 测试:
// delete ParentB
var dr = dsSample.Tables["Parent"].Select("name = 'ParentB'")[0];
dr.Delete();
// if constraints work, there should be
// multiple Child and SubChild rows affected
var childChanges = dsSample.Tables["Child"].GetChanges(DataRowState.Deleted);
var subChanges = dsSample.Tables["SubChild"].GetChanges(DataRowState.Deleted);
Console.WriteLine("Child changes: {0}, subCh changes: {1}",
childChanges.Rows.Count,
subChanges.Rows.Count);
Result: 结果:
Child changes: 3, subCh changes: 4
子更改:3,subCh更改:4
Perfect! 完善! Deleting a single parent row cascades to also delete the 3 child rows which in turn deletes 4 subchild rows.
删除单个父行也会级联删除3个子行,这又会删除4个子行。 Take care that there are rows at each level - if there are no related subchild rows, you'll get a
NulLReferenceException
on subChanges.Rows.Count
. 注意在每个级别上都有行-如果没有相关的子子行,
NulLReferenceException
在subChanges.Rows.Count
上获得subChanges.Rows.Count
。
Updating Database 更新数据库
This entails getting the changes and applying them in order. 这需要获取更改并按顺序应用它们。 Normally, the
DataAdapter
applies all inserts, updates and deletes for you at once. 通常,
DataAdapter
一次为您应用所有插入,更新和删除。 That wont work without violating constraints, so use some code to apply the changes in order: 在不违反约束的情况下将无法工作,因此请使用一些代码按顺序应用更改:
// Assuming changes were applied on DS/DT rows,
// changed rows should be duly marked, so just
// run the updates
// insert first
DataTable parentRows = dsSample.Tables["Parent"].GetChanges(DataRowState.Added);
DataTable childRows = dsSample.Tables["Child"].GetChanges(DataRowState.Added);
DataTable subChRows = dsSample.Tables["SubChild"].GetChanges(DataRowState.Added);
// dont Update the DS.Tables...it will try
// to do ALL pending changes
if (parentRows != null)
daParent.Update(parentRows);
if (childRows != null)
daChild.Update(childRows);
if (subChRows != null)
daSubCh.Update(subChRows);
// then update..order doesnt matter
parentRows = dsSample.Tables["Parent"].GetChanges(DataRowState.Modified);
childRows = dsSample.Tables["Child"].GetChanges(DataRowState.Modified);
subChRows = dsSample.Tables["SubChild"].GetChanges(DataRowState.Modified);
if (parentRows != null)
daParent.Update(parentRows);
if (childRows != null)
daChild.Update(childRows);
if (subChRows != null)
daSubCh.Update(subChRows);
// then deletes...in reverse order!
parentRows = dsSample.Tables["Parent"].GetChanges(DataRowState.Deleted);
childRows = dsSample.Tables["Child"].GetChanges(DataRowState.Deleted);
subChRows = dsSample.Tables["SubChild"].GetChanges(DataRowState.Deleted);
if (subChRows != null)
daSubCh.Update(subChRows);
if (childRows != null)
daChild.Update(childRows);
if (parentRows != null)
daParent.Update(parentRows);
// our work is done...time for cheesecake
dsSample.AcceptChanges();
Be sure to process deletes in reverse order - subChild first on up to Parent rows. 请确保以相反的顺序处理删除操作-首先在子行(最多父行)上使用subChild。 If everything worked as intended, the Access query from before should now be empty:
如果一切按预期工作,以前的Access查询现在应该为空:
et voilà ! 等!
It is not possible to tell from that SQL what you are doing (or if the DB is even modeled correctly). 无法从该SQL知道您在做什么(或者是否正确建模了数据库)。 But it is doubtful you would need an adapter for each table - some look like lookups.
但是令人怀疑的是,您是否需要为每个表使用适配器-有些看起来像查找。 In that case, they could be helper classes/objects providing that service.
在这种情况下,它们可以是提供该服务的助手类/对象。
Resources 资源资源
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.