如何创建Linq到Sql类型的临时记录而不引起重复的密钥问题?

如何创建Linq到Sql类型的临时记录而不引起重复的密钥问题?,linq,linq-to-sql,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();

我有基于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, 现在currentCrop.Crop_变种包括这个临时记录。当我插入这个网格的新记录时,它们引用了相同的作物记录,因此数据库中已经存在的这些临时记录在我提交时显示了两次,导致重复的键错误

我有一套完整的系统,可以根据用户所做的事情来检测哪些记录需要添加,哪些记录需要删除,但这种对参考文献的无情跟踪却让它变得一团糟


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

当您指定实体对象引用时,您正在创建两个对象之间的链接。在这里,您可以这样做:

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.rssfeedeitems.Add(this);”来建立链接


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

指定实体对象引用时,您正在创建两个对象之间的链接。在这里,您可以这样做:

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.rssfeedeitems.Add(this);”来建立链接


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

我建议重新访问用记录填充DataGridView(grid)的代码

然后重新访问对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; 
    }
}
public object GridSelectedItem
{
得到
{
尝试
{
if(_grid==null | | | u grid.SelectedCells.Count<1)返回null;
DataGridViewCell单元格=_grid.SelectedCells[0];
DataGridViewRow=_grid.Rows[cell.RowIndex];
if(row.DataBoundItem==null)返回null;
返回row.DataBoundItem;
}
捕获{}
返回null;
}
}
您发布的作物品种代码的性质也很难理解。由于作物的多样性似乎是作物的一个子类。当作物尚未绑定到数据库时,这会导致问题,并且在将作物品种添加到上下文时可能会导致问题


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

我建议重新访问用记录填充DataGridView(grid)的代码

然后重新访问对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; 
    }
}
public object GridSelectedItem
{
得到
{
尝试
{
if(_grid==null | | | u grid.SelectedCells.Count<1)返回null;
DataGridViewCell单元格=_grid.SelectedCells[0];
DataGridViewRow=_grid.Rows[cell.RowIndex];
if(row.DataBoundItem==null)返回null;
返回row.DataBoundItem;
}
捕获{}
返回null;
}
}
您发布的作物品种代码的性质也很难理解。由于作物的多样性似乎是作物的一个子类。当作物尚未绑定到数据库时,这会导致问题,并且在将作物品种添加到上下文时可能会导致问题


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

您能再解释一下为什么创建新的
Crop\u Variety
实例,但不希望它们被持久化。还是希望L2S在持久化它们之前找出哪些是重复的?我正在尝试为DataGridView中找到的所有记录创建实例。并非所有数据都有到datagridview的直接映射,因此我不确定是否可以进行任何类型的自动更新/插入。我正在重新调整我的保存代码,因为这个问题在我当前的系统中不断出现,但是如果有更好的方法在处理网格行数据时识别现有记录和新记录,那就太好了。你能解释一下为什么创建新的
Crop\u Variety
实例,但不希望它们被持久化吗。还是希望L2S在持久化它们之前找出哪些是重复的?我正在尝试为DataGridView中找到的所有记录创建实例。并非所有数据都有到datagridview的直接映射,因此我不确定是否可以进行任何类型的自动更新/插入。我正在重新调整我的保存代码,因为