dBSet.Local.Clear使用EF 6在WPF应用程序中抛出InvalidOperationException

时间:2014-08-26 18:46:22

标签: c# .net wpf entity-framework data-binding

我在WPF应用程序中使用EF 6。我正在尝试构建一个抽象数据库特定代码的分层架构 从应用程序的其余部分。我采用DbSet<> .Local的实例数据绑定到我的UI控件的方法,以减轻负担 变更跟踪我保持上下文很长一段时间,即从打开一个新数据库到这个时间 它已关闭。根据我的研究,基于Microsoft的这篇文章,似乎这是基于4.1之后的EF版本的推荐方法 (http://msdn.microsoft.com/en-US/data/jj574514)即使它似乎不是一个受欢迎的选择。

但是,当我尝试做最简单的事情时,我会收到异常。目前,我已将其缩小到我尝试清除时发生的这一异常 来自DbSet.Local的所有实体。请参阅下面的代码中的MVPModel.Clear()中的代码行。基本上,它试图执行:DbSet.Local.Clear()。

我注定会遇到这种方法的麻烦吗?

我使用这个类绑定到MVP风格的架构中的UI。

public class MVPModel
{
    public ObservableCollection<ConcreteModel> Models { get; set; }

    public void Attach(Database db)
    {
        this.Models = db.GetRepository<ConcreteModel>();
    }

    public void Detach()
    {
        this.Models = null;
    }

    public void Clear()
    {
        // Throwns an InvalidOperationException with the message
        // The property 'Id' is part of the object's key information and cannot be modified. 
        Models.Clear(); 
    }
}


public class ModelBase : INotifyPropertyChanged
{
    private Int32 _id;

    [Key]
    public Int32 Id
    {
        get
        {
            return this._id;
        }
        set
        {
            if (_id != value)
            {
                _id = value;
                OnPropertyChanged("Id");
            }
        }
    }

}

public class ConcreteModel : ModelBase
{
    // ...
}

public class MyDbContext : DbContext
{
    public DbSet<ConcreteModel> Models { get; set; }

}

我在EF数据库上下文周围创建了一个包装器,它释放了与DbContext相关联的非托管资源。

public class Database : IDisposable
{
        private MyDbContext _dbContext;

        /// <summary>
        /// Get a reference to a collection
        /// </summary>
        /// <typeparam name="T">ObservableCollection generic template type</typeparam>
        /// <returns>An observable collection bound to the database repository</returns>
        public ObservableCollection<T> GetRepository<T>() 
        {
            ObservableCollection<T> retValue = null;

            var dbSet = this._dbContext.Set(typeof(T));

            if (dbSet != null)
            {
                try
                {
                    // Force a query against the database to load the data. Otherwise, .Local will always be
                    // empty. This is similar to called DbSet<T>.ToList() but it saves the overhead of creating 
                    // a throw away instance of List<>.
                    dbSet.Load();
                }
                catch (Exception ex)
                {
                    // Load will fail if the database hasn't been created yet, e.g. File|New
                    ex.Post();
                }

                retValue = dbSet.Local as ObservableCollection<T>;
                Debug.Assert(retValue != null);            
            }

            return retValue;
        }

    // ...
}

这是例外的副本:

发生了System.InvalidOperationException   的HResult = -2146233079   消息=属性&#39; Id&#39;是对象的关键信息的一部分,不能修改。   来源=的EntityFramework   堆栈跟踪:        在System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInProperty(Int32 ordinal,Boolean detectOnlyComplexProperties,Boolean detectOnly)   InnerException:

来自我的调用堆栈的更多内容:

System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInProperty(int ordinal = 0, bool detectOnlyComplexProperties = false, bool detectOnly = false) 
System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInProperties(bool detectOnlyComplexProperties = false) 
System.Data.Entity.Core.Objects.ObjectStateManager.DetectChangesInScalarAndComplexProperties(System.Collections.Generic.IList<System.Data.Entity.Core.Objects.EntityEntry> entries = Count = 20)    
System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()  
System.Data.Entity.Core.Objects.ObjectContext.DetectChanges()   
System.Data.Entity.Internal.InternalContext.DetectChanges(bool force = false)   
...

0 个答案:

没有答案