繁体   English   中英

如何使用ado.net将特定父类别的子类别插入表中?

[英]How to insert child category by specific parent category into table using ado.net?

我正在尝试将Excel中的类别和子类别插入数据库表中。

我有一个包含一些数据,并从我创建这个Excel文件1个Excel文件dataset ,它含有许多的datatables

在这一dataset我有2个datatables中的这种形式:

具有记录的数据表0: 类别

ParentCategory Description
  Electronics   jhdkhsd
  Sports        kjshfhs

具有记录的数据表1: SubCategory

Subcategory ParentCategory  Description
  Mobile       Electronics   weprwp
  Tv           Electronics   sdflskd
  Balls        Sports        kjshdfkjh
  Shoes        Sports        uytuyt

现在我的数据库表是这样的:

类别Id,Name,Description,parentid

到目前为止,我已成功插入父类别,但现在尝试插入子类别,但这是我目前正在努力的地方。

到目前为止,这是我的代码:

var dsFinal = new DataSet();

    //Some code to read excel sheets and data from excel and create datatables and records with it.


 dsControlSheet.Tables[0].Columns.Add("Id");
 DataColumn parentId = new DataColumn("ParentId", typeof(int));
 parentId.DefaultValue = 0;
 dsFinal.Tables[0].Columns.Add(parentId);
 dsFinal.Relations.Add("Abc",dsFinal.Tables[0].Columns["ParentCategory"],
 dsFinal.Tables[1].Columns["ParentCategory"],false); //creating relation ship between Category datatable
// and SubCategory datatable on field ParentCategory



using (SqlConnection connection = new SqlConnection(""))
     {
       SqlDataAdapter adapter = new SqlDataAdapter();
       var insertCommand = new SqlCommand("insert into Category (Name,Description) values (@ParentCategory,@Description) SET @Id = SCOPE_IDENTITY()", connection);
       var parameter = insertCommand.Parameters.Add("@Id", SqlDbType.Int, 0, "Id");
       insertCommand.Parameters.Add("@ParentCategory", SqlDbType.NVarChar, 50, "ParentCategory");
       insertCommand.Parameters.Add("@Description", SqlDbType.NVarChar, 50, "Description");
       parameter.Direction = ParameterDirection.Output;
       insertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
       adapter.InsertCommand = insertCommand;
       adapter.Update(dsFinal.Tables[0]); //successfully inserted parent category and got autoincremented value in Id column of my 0th datatable

       //trying to insert child category using above insert command
       foreach (DataRow parentCategory in dsFinal.Tables[0].Rows)
                  {
                      var child = parentCategory.GetChildRows("Abc").CopyToDataTable();//get child category of particular parent 
                      adapter.Update(child);
                  }
     }

这里在最后一个循环中插入子类别; 我对如何使用相同的insertCommand变量插入子类别感到困惑?

更新 :我已经使用数据表datatable Expression来计算像这样的parentid

using (SqlConnection connection = new SqlConnection(""))
         {
           SqlDataAdapter adapter = new SqlDataAdapter();
           var insertCommand = new SqlCommand("insert into Category (Name,Description) values (@ParentCategory,@Description) SET @Id = SCOPE_IDENTITY()", connection);
           var parameter = insertCommand.Parameters.Add("@Id", SqlDbType.Int, 0, "Id");
           insertCommand.Parameters.Add("@ParentCategory", SqlDbType.NVarChar, 50, "ParentCategory");
           insertCommand.Parameters.Add("@Description", SqlDbType.NVarChar, 50, "Description");
           parameter.Direction = ParameterDirection.Output;
           insertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
           adapter.InsertCommand = insertCommand;
           adapter.Update(dsFinal.Tables[0]); //successfully inserted parent category and got autoincremented value in Id column of my 0th datatable

          //For inserting child category..
           //added column parentid to store child category
           SqlDataAdapter da = new SqlDataAdapter();
           dsFinal.Tables[1].Columns.Add("ParentId", typeof(int), "IIF(Parent.ParentCategory=ParentCategory,parent.Id,0)");
           var insertChildCategoryCommand = new SqlCommand("insert into Category (Name,Description,ParentId) values (@Subcategory,@Description,@ParentId) SET @Id = SCOPE_IDENTITY()", connection);
           var parameter1 = insertChildCategoryCommand.Parameters.Add("@Id", SqlDbType.Int, 0, "Id");
           insertChildCategoryCommand.Parameters.Add("@Subcategory", SqlDbType.NVarChar, 50, "Subcategory");
           insertChildCategoryCommand.Parameters.Add("@Description", SqlDbType.NVarChar, 50, "Description");
           insertChildCategoryCommand.Parameters.Add("@ParentId", SqlDbType.int, 0, "ParentId");
           parameter1.Direction = ParameterDirection.Output;
           insertChildCategoryCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
           da.InsertCommand = insertChildCategoryCommand;
           //Error here that computed column cannot be inserted.Here computed column is parentid
           da.Update(dsFinal.Tables[1]);            
         }

错误Computed column(parentid) cannot be inserted

您即将获得最新代码。

唯一的问题是,不允许将计算出的列用于插入/更新数据库表。 顺便说一句,错误消息不是“ 无法插入计算列(父代)。 ”,而是:

SourceColumn'ParentId'的列映射失败,因为DataColumn'ParentId'是计算列。

我可以同意该信息可能会更好,而且我也没有找到任何描述此信息的文档。 最有可能的理由是,通常不存储计算列。

无论原因是什么,这都是事实。 除了创建常规列并手动填充数据外,您别无选择。

有很多方法可以做到这一点(有效和无效),但是一旦创建了关系,就可以使用DataRow.GetParentRow方法来找到相关的类别记录。

话虽如此,替换行

dsFinal.Tables[1].Columns.Add("ParentId", typeof(int), 
    "IIF(Parent.ParentCategory=ParentCategory,parent.Id,0)");

包含以下代码段:

var dtSubCategory = dsFinal.Tables[1];
dtSubCategory.Columns.Add("ParentId", typeof(int));
foreach (var drSubCategory in dtSubCategory.AsEnumerable())
{
    var drCategory = drSubCategory.GetParentRow("Abc");
    drSubCategory["ParentId"] = drCategory != null ? drCategory["Id"] : 0;
}

到此为止。

编辑:让我说清楚。 唯一关键的操作是按名称查找类别ID。 与尝试使用关系和GetParentRow等效于评估访问parent的表达式。 数据关系在内部维护用于支持此类操作的查找结构。

如果要获得最佳性能,则不要创建关系,而要创建字典。 给您所需的名称(字符串),找到相应的ID(整数),因此Dictionary<string, int>是该的理想选择:

var categoryIds = dsFinal.Tables[0].AsEnumerable().ToDictionary(
    dr => dr.Field<string>("ParentCategory"), // key
    dr => dr.Field<int>("Id") // value
);
var dtSubCategory = dsFinal.Tables[1];
dtSubCategory.Columns.Add("ParentId", typeof(int));
foreach (var drSubCategory in dtSubCategory.AsEnumerable())
{
    int categoryId;
    categoryIds.TryGetValue(drSubCategory.Field<string>("ParentCategory"), out categoryId);
    drSubCategory["ParentId"] = categoryId;
}

更改您的关系,使其使用Id和ParentId,并且您的第一个解决方案将正常工作。

当您更新第一个表并获取自动递增的值时,它将通过该关系自动更新第二个表。 这是一个例子。

DataSet ds = new DataSet();
DataTable dt = new DataTable();
var colParent = dt.Columns.Add("id", typeof(int));

DataTable dtChild = new DataTable();
var colChild = dtChild.Columns.Add("parentid", typeof(int));

ds.Tables.Add(dt);
ds.Tables.Add(dtChild); 
ds.Relations.Add("relation1", colParent, colChild);

DataRow rowParent = dt.NewRow();
rowParent["id"] = 1;
dt.Rows.Add(rowParent);
DataRow rowChild = dtChild.NewRow();
rowChild["parentid"] = rowParent["id"];
dtChild.Rows.Add(rowChild);

// at this point, parentid from rowChild is "1".    
rowParent["id"] = 10; // DataAdapter.Update simulation.
// and now parentid from rowChild has been update via the relation to "10". 

当使用这种方法时,我通常将列设置为一个临时的“ id”值,方法是将该列设置为具有种子和步骤设置为-1的标识列。 这将在第三行之后。

colParent.AutoIncrement = true;
colParent.AutoIncrementSeed = -1;
colParent.AutoIncrementStep = -1;

除非您真的需要在这些字符串字段上建立关系,否则不需要执行任何循环,计算列或任何过于复杂的操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM