LINQ to SQL DuplicateKeyException问题

时间:2009-07-15 15:20:09

标签: linq-to-sql

我正在使用LINQ2SQL,我有一个名为Customers的表,有三列

CustmerID,CustomerCode,CustomerName

CustmerID是Primery Key(和Identity = yes),而CustomerCode只是UniqueKey。

当我使用带有重复客户代码的LINQ to SQL更新此表时,我希望看到DuplicateKeyException,但它将进入常规异常块而不是DuplicateKeyException块。有什么想法吗?

这是代码

public void Update(Customer cust)         {             使用(LINQDemoDataContext db = new LINQDemoDataContext())             {                 Customers entity = CustomerMapper.ToEntity(new Customers(),cust);

            try
            {
                db.Customers.Attach(entity, true);
                db.SubmitChanges();
            }

            //Concurrency Exception
            catch (ChangeConflictException)
            {                               
                throw new ChangeConflictException("A concurrency error occurred!");
            }

            //duplicate record
            catch (DuplicateKeyException)
            {
                throw new DuplicateKeyException(entity.CustmerCode);
            }

            //everything else
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

我正在使用VisualWebDeveloperExpress 2008和SQL Express 2005。

谢谢&问候, Supremestar

3 个答案:

答案 0 :(得分:2)

如果内存服务,我可能在这里错了,DuplicateKeyException仅触发表的主键。

答案 1 :(得分:0)

我遇到了同样的问题,即使它们没有插入到数据库中,重复的密钥对象仍保留在内存中。我提出了以下工作:

    MyDataContext _myDataContext = new MyDataContext(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);

    public void AddObject(object myObject)
    {
        try
        {
            _myDataContext.Objects.InsertOnSubmit(myObject);
            _myDataContext.SubmitChanges();
        }
        catch (System.Data.Linq.DuplicateKeyException ex)
        {
            _myDataContext = new MyDataContext(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
            throw ex;

然后,您可以在调用者中捕获并处理(或忽略)抛出的DuplicateKeyException。

另一种解决方法(虽然效率低下和内存占用)是在AddObject方法中创建一个新的数据上下文,而不是使用实例化为类成员的共享数据上下文。

答案 2 :(得分:0)

添加一个来自不同DataContext的实体时遇到了问题 (我将一个BarDb-Entity的FooDb-Property绑定到DropDownList中的SelectedValue,它有一个来自短生命DataContext的Table作为DataSource) 我们来看看Linq2Sql内部的Attach(实体):

private void attach_FooDb(FooDb entity){
    this.SendPropertyChanging();
    entity.BarDb = this;
}

BarDb Property设置:

set{
    BarDb previousValue = this._BarDb.Entity;
    if (((previousValue != value) || (this._BarDb.HasLoadedOrAssignedValue == false))){
        this.SendPropertyChanging();
        if ((previousValue != null)){
            this._BarDb.Entity = null;
            previousValue.FooDb.Remove(this);
        }

        this._BarDb.Entity = value;

        if ((value != null)){
            value.FooDb.Add(this);
            this._FK_Bar = value.ID;
        }else{
            this._FK_Bar = default(System.Guid);
        }
        this.SendPropertyChanged("BarDb");
    }
}

因此,当附加到FooDb时,相应的DataContext会将BarDb实体识别为新创建和添加的,即使它已经存在于数据库中。

您可以通过以下方式解决:

  • 仅使用单个DataContext或
  • 在提交DataContext中创建一个BarDb_safe属性,该属性首先从数据库中请求“相等”实体,应用所有属性,然后以通常的方式附加它。