【问题标题】:Constraint error in adding Multi rows to master/detail dataset将多行添加到主/详细数据集时出现约束错误
【发布时间】:2014-05-11 10:03:02
【问题描述】:

我有 2 个绑定到主/详细关系的 dataGridView。 当我尝试向主 dataGridView 添加第二行时,出现以下错误。

system.data.constraintexception 列“Project Customer UBF Id”被限制为唯一。值 '' 已经存在 数据关系。

我可以将多行添加到子 DataGridView,如果我删除表之间的 DataRelation,我可以将多行添加到主视图。 此外,如果我使用下一个自动增量值手动输入主键的主键,我可以添加多行,以及针对这些行添加详细信息。

这些表是在 SQL Server 中使用自动增量主键设置的。

任何帮助克服此错误将不胜感激

private void getData()
{
    try
    {
        conn = new SqlConnection(connstr);
        conn.Open();

        // Create a DataSet.
        data = new DataSet();
        data.Locale = System.Globalization.CultureInfo.InvariantCulture;

        string sqlStr = "SELECT [Project Customer UBF].* FROM [Project Customer UBF]; ";                    

        // Add data from the Customers table to the DataSet.
        masterDataAdapter = new
            SqlDataAdapter(sqlStr, conn);

        masterDataAdapter.Fill(data, "Customers");

        // Add data from the Orders table to the DataSet.
        detailsDataAdapter = new
            SqlDataAdapter("SELECT [Project Customer Discount].* FROM [Project Customer Discount]", conn);
        detailsDataAdapter.Fill(data, "Discounts");

        // Establish a relationship between the two tables.
        DataRelation relation = new DataRelation("CustDist",
            data.Tables["Customers"].Columns["Project Customer UBF Id"],
            data.Tables["Discounts"].Columns["Project Customer UBF Id"]);
        data.Relations.Add(relation);


        // Bind the master data connector to the Customers table.
        masterBindingSource.DataSource = data;
        masterBindingSource.DataMember = "Customers";
        masterBindingSource.Filter = "[Project Id] =" + _projectID;

        // Bind the details data connector to the master data connector, 
        // using the DataRelation name to filter the information in the  
        // details table based on the current row in the master table. 
        detailsBindingSource.DataSource =  masterBindingSource;
        detailsBindingSource.DataMember = "CustDist";
        conn.Close();              
    }
    catch (SqlException)
    {
        MessageBox.Show("To run this example, replace the value of the " +
            "connectionString variable with a connection string that is " +
            "valid for your system.");
    }
}

private void ProjectEdit_Load(object sender, EventArgs e)
{
    dataGridView1.DataSource = masterBindingSource;
    dataGridView2.DataSource = detailsBindingSource;
    getData();
}

【问题讨论】:

    标签: c# datagridview master-detail datarelation


    【解决方案1】:

    通过为主/父数据表和详细/子数据表生成自己的更新、删除和添加命令来解决:

    private void GenerateCommands() {
    
        masterDataAdapter.InsertCommand = new SqlCommand();
        masterDataAdapter.InsertCommand.CommandText = "INSERT INTO [Project Customer UBF]([Project Id], [Customer Id]," +
            "[Host Support], Warehoused,[List Price per Case]) "  
        + " VALUES (@ProjID, @CustID, 1, @Ware, 4); "
        + " SELECT [Project Customer UBF Id],[Project Id], [Customer Id]," +
            "[Host Support], Warehoused,[List Price per Case]"
        + " FROM [Project Customer UBF] WHERE ([Project Customer UBF Id]= SCOPE_IDENTITY())";
        masterDataAdapter.InsertCommand.Connection = conn;
    
        masterDataAdapter.InsertCommand.Parameters.Add("@ProjID", SqlDbType.Int,4,"Project Id");
        masterDataAdapter.InsertCommand.Parameters.Add("@CustID", SqlDbType.Int,4,"Customer Id");
        masterDataAdapter.InsertCommand.Parameters.Add("@Host", SqlDbType.Bit,1,"Host Support");
        masterDataAdapter.InsertCommand.Parameters.Add("@Ware", SqlDbType.Bit,1,"Warehoused");
        masterDataAdapter.InsertCommand.Parameters.Add("@List", SqlDbType.Float,8,"List Price per Case");
    
    
        masterDataAdapter.UpdateCommand = new SqlCommand();
        masterDataAdapter.UpdateCommand.CommandText = "UPDATE [Project Customer UBF] SET [Project Id] = @ProjID, "  
        + " [Customer Id] = @CustID, [Host Support] = @Host, Warehoused = @Ware, [List Price per Case] = @List " 
            + "WHERE ([Project Customer UBF Id] = @PCID); "; 
    
        masterDataAdapter.UpdateCommand.Connection = conn;
    
        masterDataAdapter.UpdateCommand.Parameters.Add("@ProjID", SqlDbType.Int,4,"Project Id");
        masterDataAdapter.UpdateCommand.Parameters.Add("@CustID", SqlDbType.Int,4,"Customer Id");
        masterDataAdapter.UpdateCommand.Parameters.Add("@Host", SqlDbType.Bit,1,"Host Support");
        masterDataAdapter.UpdateCommand.Parameters.Add("@Ware", SqlDbType.Bit,1,"Warehoused");
        masterDataAdapter.UpdateCommand.Parameters.Add("@List", SqlDbType.Float,8,"List Price per Case");
        masterDataAdapter.UpdateCommand.Parameters.Add("@PCID", SqlDbType.Int,4,"Project Customer UBF Id");
    
        masterDataAdapter.DeleteCommand = new SqlCommand();
        masterDataAdapter.DeleteCommand.CommandText = "DELETE FROM [Project Customer UBF] "
            + " WHERE ([Project Customer UBF Id] = @PCID);";
    
        masterDataAdapter.DeleteCommand.Connection = conn;
        masterDataAdapter.DeleteCommand.Parameters.Add("@PCID", SqlDbType.Int,4,"Project Customer UBF Id"); 
    
        detailsDataAdapter.InsertCommand = new SqlCommand();
        detailsDataAdapter.InsertCommand.CommandText = "INSERT INTO [Project Customer Discount]([Project Customer UBF Id], "
    + " [Discount Type], [Discount Amt], [Discount UOM]) " 
            + " VALUES (@PCID, @Type, @Amt, @UOM); " 
            + " SELECT [Discount Id],[Project Customer UBF Id], "
    + " [Discount Type], [Discount Amt], [Discount UOM] " 
            + " FROM [Project Customer Discount] WHERE ([Discount Id] = SCOPE_IDENTITY())";
        detailsDataAdapter.InsertCommand.Connection = conn;
    
        detailsDataAdapter.InsertCommand.Parameters.Add("@PCID", System.Data.SqlDbType.Int,4, "Project Customer UBF Id");
        detailsDataAdapter.InsertCommand.Parameters.Add("@Type", SqlDbType.Int,4,"Discount Type");
        detailsDataAdapter.InsertCommand.Parameters.Add("@Amt", SqlDbType.Float,8,"Discount Amt");
        detailsDataAdapter.InsertCommand.Parameters.Add("@UOM", SqlDbType.NVarChar,2,"Discount UOM");
    
        detailsDataAdapter.UpdateCommand = new SqlCommand();
        detailsDataAdapter.UpdateCommand.CommandText = "UPDATE [Project Customer Discount] SET [Project Customer UBF Id] = @PCID, "
        + " [Discount Type] = @Type, [Discount Amt] = @Amt, [Discount UOM] = @UOM "
            + "WHERE ([Discount Id] = @DID); ";
        detailsDataAdapter.UpdateCommand.Connection = conn;
    
        detailsDataAdapter.UpdateCommand.Parameters.Add("@PCID", System.Data.SqlDbType.Int, 4, "Project Customer UBF Id");
        detailsDataAdapter.UpdateCommand.Parameters.Add("@Type", SqlDbType.Int, 4, "Discount Type");
        detailsDataAdapter.UpdateCommand.Parameters.Add("@Amt", SqlDbType.Float, 8, "Discount Amt");
        detailsDataAdapter.UpdateCommand.Parameters.Add("@UOM", SqlDbType.NVarChar, 2, "Discount UOM");
        detailsDataAdapter.InsertCommand.Parameters.Add("@DID", System.Data.SqlDbType.Int, 4, "Discount Id");
    
        detailsDataAdapter.DeleteCommand = new SqlCommand();
        detailsDataAdapter.DeleteCommand.CommandText = "DELETE FROM [Project Customer Discount] "
            + " WHERE ([Discount Id] = @DID);";
        detailsDataAdapter.DeleteCommand.Connection = conn;
    
        detailsDataAdapter.DeleteCommand.Parameters.Add("@DID", System.Data.SqlDbType.Int, 4, "Discount Id");
    }
    

    并为父/主数据表的主键创建一个自动增量。自动增量从 -1 开始并以 -1 递增以保持唯一性。

    private void CreateRelations() {
        DataRelation relation = new DataRelation("CustDist",
            data.Tables["Customers"].Columns["Project Customer UBF Id"],
            data.Tables["Discounts"].Columns["Project Customer UBF Id"]);
        data.Relations.Add(relation);
    
        data.Tables["Customers"].Columns["Project Customer UBF Id"].AutoIncrement = true;
        data.Tables["Customers"].Columns["Project Customer UBF Id"].AutoIncrementSeed = -1;
        data.Tables["Customers"].Columns["Project Customer UBF Id"].AutoIncrementStep = -1;
    }
    

    创建主/父明细/子数据集的代码:

    private void GetData()
    {
        try
        {
    
            conn = new SqlConnection(connstr);
            conn.Open();
    
            // Create a DataSet.
            data = new DataSet();
            data.Locale = System.Globalization.CultureInfo.InvariantCulture;
    
            string sqlStr = "SELECT [Project Customer UBF].* FROM [Project Customer UBF]; "; //WHERE [Project Customer UBF].[Project Id] = " +_projectID;                       
    
            // Add data from the Customers table to the DataSet.
            masterDataAdapter = new
                SqlDataAdapter(sqlStr, conn);
    
            masterDataAdapter.Fill(data, "Customers");
    
            // Add data from the Orders table to the DataSet.
            detailsDataAdapter = new
                SqlDataAdapter("SELECT [Project Customer Discount].* FROM [Project Customer Discount]", conn);
            detailsDataAdapter.Fill(data, "Discounts");
    
            detailsDataAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
    
            GenerateCommands();
            CreateRelations();
    
            // Bind the master data connector to the Customers table.
            masterBindingSource.DataSource = data;
            masterBindingSource.DataMember = "Customers";
            masterBindingSource.Filter = "[Project Id] =" + _projectID;
    
            // Bind the details data connector to the master data connector, 
            // using the DataRelation name to filter the information in the  
            // details table based on the current row in the master table. 
            detailsBindingSource.DataSource = masterBindingSource;
            detailsBindingSource.DataMember = "CustDist";
            conn.Close();
    
        }
        catch (SqlException)
        {
            MessageBox.Show("To run this example, replace the value of the " +
                "connectionString variable with a connection string that is " +
                "valid for your system.");
        }
    }
    

    将更改保存回数据库:

    if (data.Tables["Discounts"].GetChanges(System.Data.DataRowState.Deleted) != null)
    {
        detailsBindingSource.EndEdit();
        System.Data.DataTable DeletedChildRecords =
            data.Tables["Discounts"].GetChanges(System.Data.DataRowState.Deleted);
    
        try
        {
            if (DeletedChildRecords != null)
            {
                SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(detailsDataAdapter);
                detailsDataAdapter.Update(data.Tables["Discounts"].Select(null, null, DataViewRowState.Deleted));
            }
    
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
        finally
        {
            if (DeletedChildRecords != null)
            {
                DeletedChildRecords.Dispose();
            }
        }
    }
    
    if (data.Tables["Customers"].GetChanges(System.Data.DataRowState.Added) != null || data.Tables["Customers"].GetChanges(System.Data.DataRowState.Modified) != null ||
        data.Tables["Customers"].GetChanges(System.Data.DataRowState.Deleted) != null)
    {
        masterBindingSource.EndEdit();
        try
        {
            SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(masterDataAdapter);
            masterDataAdapter.Update(data.Tables["Customers"].Select(null, null, DataViewRowState.Deleted));
            masterDataAdapter.Update(data.Tables["Customers"].Select(null, null, DataViewRowState.ModifiedCurrent));
            masterDataAdapter.Update(data.Tables["Customers"].Select(null, null, DataViewRowState.Added));
    
        }
        catch (System.Exception err)
        {
            MessageBox.Show(err.ToString());                        
        }
    }
    
    if (data.Tables["Discounts"].GetChanges(System.Data.DataRowState.Added) != null || data.Tables["Discounts"].GetChanges(System.Data.DataRowState.Modified) != null)
    {
        detailsBindingSource.EndEdit();
        System.Data.DataTable NewChildRecords =
            data.Tables["Discounts"].GetChanges(System.Data.DataRowState.Added);
    
        System.Data.DataTable ModifiedChildRecords =
            data.Tables["Discounts"].GetChanges(System.Data.DataRowState.Modified);
    
        try
        {
            if (ModifiedChildRecords != null)
            {
                SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(detailsDataAdapter);
                detailsDataAdapter.Update(data.Tables["Discounts"].Select(null, null, DataViewRowState.ModifiedCurrent));
            }
    
            if (NewChildRecords != null)
            {
                SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(detailsDataAdapter);
                detailsDataAdapter.Update(data.Tables["Discounts"].Select(null, null, DataViewRowState.Added));
            }
    
        }
    
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    
        finally
        {
            if (NewChildRecords != null)
            {
                NewChildRecords.Dispose();
            }
            if (ModifiedChildRecords != null)
            {
                ModifiedChildRecords.Dispose();
            }
        }
    }
    

    将数据源绑定到 dataGridViews:

    dataGridView1.DataSource = masterBindingSource;
    dataGridView2.DataSource = detailsBindingSource;
    GetData();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多