如何创建Linq-To-Sql类型的临时记录而不会导致重复的密钥问题?

时间:2011-11-15 12:55:15

标签: linq linq-to-sql

我有基于我的DataGridView生成记录的代码。这些记录是临时的,因为其中一些记录已存在于数据库中。

        Crop_Variety v = new Crop_Variety();
        v.Type_ID = currentCropType.Type_ID;
        v.Variety_ID = r.Cells[0].Value.ToString();
        v.Description = r.Cells[1].Value.ToString();
        v.Crop = currentCrop;
        v.Crop_ID = currentCrop.Crop_ID;

不幸的是在这一小段代码中,因为我说v.Crop = currentCrop, now currentCrop.Crop_Varieties包含此临时记录。当我去插入新网格的记录时,它们会引用相同的裁剪记录,因此数据库中已存在的这些临时记录会在我提交时出现两次导致重复键错误。

我有一个完整的系统,用于检测需要添加哪些记录以及根据用户的操作需要删除哪些记录,但是这种不断追踪的参考文件会让它变得无聊。

有没有办法阻止Linq-To-Sql自动将这些临时记录添加到其表集合中?

2 个答案:

答案 0 :(得分:1)

我建议重新访问使用记录填充DataGridView(网格)的代码。

然后重新访问对GridView中的项进行操作的代码,请记住,您可以使用以下代码从网格行中获取绑定项:

public object GridSelectedItem
{
    get
    {
        try
        {
            if (_grid == null || _grid.SelectedCells.Count < 1) return null;
            DataGridViewCell cell = _grid.SelectedCells[0];
            DataGridViewRow row = _grid.Rows[cell.RowIndex];
            if (row.DataBoundItem == null) return null;
            return row.DataBoundItem;
        }
        catch { }
        return null; 
    }
}

您也很难理解您发布的Crop_Variety代码的性质。由于Crop_Variety似乎是Crop的一个子类。当Crop尚未绑定到数据库时,这会导致问题,并且当您将Crop_Variety添加到上下文时可能会导致问题。

对于这种类型的Form应用程序,我通常在表单类中有List _dataList,然后主网格通过ObjectBindingList或其他方式绑定到该列表。这样,_dataList保存了所有需要在需要时保存的数据(用户点击保存)。

答案 1 :(得分:0)

分配实体对象引用时,您将在两个对象之间创建链接。你在这里这样做:

v.Crop = currentCrop;

只有一种方法可以避免这种情况:修改生成的代码或生成/编写自己的代码。我永远不会这样做。

我认为通过编写自定义DTO类而不是重用生成的实体,您会更好。我已经做了两种方法,我更喜欢后者。

编辑:以下是一些示例生成代码:

    [global::System.Data.Linq.Mapping.AssociationAttribute(Name="RssFeed_RssFeedItem", Storage="_RssFeed", ThisKey="RssFeedID", OtherKey="ID", IsForeignKey=true, DeleteOnNull=true, DeleteRule="CASCADE")]
    public RssFeed RssFeed
    {
        get
        {
            return this._RssFeed.Entity;
        }
        set
        {
            RssFeed previousValue = this._RssFeed.Entity;
            if (((previousValue != value) 
                        || (this._RssFeed.HasLoadedOrAssignedValue == false)))
            {
                this.SendPropertyChanging();
                if ((previousValue != null))
                {
                    this._RssFeed.Entity = null;
                    previousValue.RssFeedItems.Remove(this);
                }
                this._RssFeed.Entity = value;
                if ((value != null))
                {
                    value.RssFeedItems.Add(this);
                    this._RssFeedID = value.ID;
                }
                else
                {
                    this._RssFeedID = default(int);
                }
                this.SendPropertyChanged("RssFeed");
            }
        }
    }

正如您所看到的,生成的代码通过说“value.RssFeedItems.Add(this);”来建立链接。

如果您有许多实体需要许多DTO,您可以使用反射代码生成DTO类。

相关问题