dbset.local更新数据库:无法将重复值插入唯一索引

时间:2012-04-27 04:59:18

标签: c# wpf entity-framework mvvm local

我在EF 4.3.1上调用entities.savechanges()时遇到错误。我的数据库是一个sql ce v4商店,我在mvvm模式编码。我有一个本地版本的上下文,我发送到一个可观察的集合和修改等。这工作正常,当我在数据库中没有行时调用savechanges()时,对象保持正常。当我重新加载应用程序时,对象将按照它们应该填充在我的列表框中,但是如果我添加另一个对象并调用savechanges(),则会收到一条错误消息,指出无法将重复值插入到唯一索引中。

根据我的理解,这意味着上下文试图将我的实体保存到数据存储区,但它似乎是添加我未触及的原始对象以及新的对象。我认为这会让他们独自一人,因为他们的状态没有改变。

private void Load()
    {
        entities.Properties.Include("Images").Load();
        PropertyList = new ObservableCollection<Property>();
        PropertyList = entities.Properties.Local;        

        //Sort the list (based on previous session stored in database)
        var sortList = PropertyList.OrderBy(x => x.Sort).ToList();
        PropertyList.Clear();
        sortList.ForEach(PropertyList.Add);

        propertyView = CollectionViewSource.GetDefaultView(PropertyList);
        if (propertyView != null) propertyView.CurrentChanged += new System.EventHandler(propertyView_CurrentChanged);     


        private void NewProperty()
    {
        try
        {
            if (PropertyList != null)
            {                                             
                Property p = new Property()
                    {
                        ID = Guid.NewGuid(),
                        AgentName = "Firstname Lastname",
                        Address = "00 Blank Street",
                        AuctioneerName = "Firstname Lastname",
                        SaleTitle = "Insert a sales title",
                        Price = 0,
                        NextBid = 0,
                        CurrentImage = null,
                        Status = "Auction Pending",
                        QuadVis = false,
                        StatVis = false, //Pause button visibility
                        Sort = PropertyList.Count + 1,                            
                    };

                PropertyList.Add(p);
                SaveProperties();
            }

        private void SaveProperties()
    {
        try
        {               
            foreach (var image in entities.Images.Local.ToList())
            {
                if (image.Property == null)
                    entities.Images.Remove(image);
            }                
        }

        catch (Exception ex)
        {
            System.Windows.MessageBox.Show(ex.Message);
        }

        entities.SaveChanges();
    }

2 个答案:

答案 0 :(得分:1)

听起来您正在将现有实体添加到上下文(标记它们以进行插入),而不是附加它们(将它们标记为现有的,未经修改)。

我也不确定新的Guid()没有返回相同的guid ...我总是使用Guid.NewGuid()http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx

答案 1 :(得分:1)

如果没有对此处的所有代码进行评论,这就会导致您提出的具体问题:

//Sort the list (based on previous session stored in database) 
var sortList = PropertyList.OrderBy(x => x.Sort).ToList(); 
PropertyList.Clear(); 
sortList.ForEach(PropertyList.Add); 

此代码:

  • 从已查询的实体开始,并被上下文跟踪为未更改的实体。也就是说,已知已存在于数据库中的实体。
  • 创建这些实体的新排序列表。
  • 在本地集合上调用Clear,导致每个被跟踪实体被标记为已删除并从集合中删除。
  • 将每个实体添加回上下文,使其现在处于已添加状态,这意味着它是新的,并且在调用SaveChanges时将保存到数据库中,

如此有效地告诉EF,数据库中存在的所有实体实际上都不存在并且需要保存。所以它试图这样做,它会导致您看到的异常。

要解决此问题,请不要清除DbContext本地集合并添加实体。相反,您应该使用本地集合在视图中进行排序以支持视图。