实体对象不能由通用存储库中的IEntityChangeTracker的多个实例引用 [英] Entity object cannot be referenced by multiple instances of IEntityChangeTracker in a generic repository

查看:691
本文介绍了实体对象不能由通用存储库中的IEntityChangeTracker的多个实例引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这个 tugberkugurlu ,这是...

  public interface IGenericRepository&T ;其中T:class {

IQueryable< T>得到所有();
IQueryable< T> FindBy(表达式< Func< T,bool>>谓词);
void Add(T entity);
void Delete(T entity);
void Edit(T entity);
void Save();
}

和此通用存储库



public abstract class GenericRepository< C,T> :
IGenericRepository< T>其中T:class C:DbContext,new(){

private C _entities = new C();
public C Context {

get {return _entities; }
set {_entities = value; }
}

public virtual IQueryable< T> GetAll(){

IQueryable< T> query = _entities.Set< T>();
返回查询;
}

public IQueryable< T> FindBy(System.Linq.Expressions.Expression< Func< T,bool>> predicate){

IQueryable< T> query = _entities.Set< T>()。Where(predicate);
返回查询;
}

public virtual void Add(T entity){
_entities.Set< T>()。Add(entity);
}

public virtual void Delete(T entity){
_entities.Set&T;()。Remove(entity);
}

public virtual void Edit(T entity){
_entities.Entry(entity).State = System.Data.EntityState.Modified;
}

public virtual void Save(){
_entities.SaveChanges();
}
}

现在可以这样使用...

  public class FooRepository:
GenericRepository&FooBarEntities,Foo>,IFooRepository {

public Foo GetSingle(int fooId){

var query = GetAll()。FirstOrDefault(x => x.FooId == fooId);
返回查询;
}
}

现在,一切都好,直到我有一个自我引用的实体,像这样...

  public class Question 
{
[Key]
public string QuestionID {get;组; }

public string QuestionNumber {get;组; }

public string Message {get;组; }

public DateTime? DatePosted {get;组; }

public DateTime?修改{get;组; }

public bool HasSubgroups {get;组; }

public string ApplicationUserId {get;组; }
[ForeignKey(ApplicationUserId)]
public virtual ApplicationUser ApplicationUser {get;组; }

public string PaperID {get;组; }
[ForeignKey(PaperID)]
public virtual PaperEntity Paper {get;组; }

public ICollection< QuestionTag>标签{get;组; }

public ICollection< QuestionVote>投票{get;组; }

public virtual ICollection< Answer>答案{get;组; }

public virtual ICollection< QuestionComment> QuestionComments {get;组; }

public string ParentQuestionID {get;组; }
[ForeignKey(ParentQuestionID)]
public virtual Question QuestionReference {get;组; }
public virtual ICollection< Question>问题{get;组; }
}

如您所见,我的模型允许我有子问题一个问题这是我如何实现它...

  dynamic model = modela; 

string q_id = model.QuestionID.ToString();

var question = q_id.IsNullOrEmpty()? null:await questionRepository.FindBy(id => id.QuestionID == q_id);

if(question == null)
{
question = new Question
{
QuestionID = Guid.NewGuid()ToString(D )
QuestionNumber = model.ParentQuestionNumber,
PaperID = model.PaperID,
Message = model.QuestionTitle,
ApplicationUserId = userid,
DatePosted = DateTime.UtcNow,
标签=新列表< QuestionTag>()
};

await questionRepository.Add(question);
}

var questionQuestion = new Question
{
QuestionID = Guid.NewGuid()ToString(D),
ParentQuestionID =问题。 QuestionID,
QuestionNumber = model.QuestionNumber,
PaperID = question.PaperID,
Message = model.Message,
ApplicationUserId = userid,
DatePosted = DateTime.UtcNow,
标签=新列表< QuestionTag>()

};

question.Questions = new List< Question> {questionQuestion};

await questionRepository.Update(question);
await questionRepository.Save();

之后,我能够保存第一个子问题,第二个问题引发错误。 ..

  _ctx.Entry(entity).State = EntityState.Modified; 

说...

  EntityFramework.dll中发生类型为System.InvalidOperationException的第一次机会异常

附加信息:实体对象不能被IEntityChangeTracker的多个实例引用。

我甚至尝试使用 IDisposable code> GenericRepository 没有运气...任何提示嗅觉帮助将高度赞赏...

解决方案

我从此示例 ...

  public class UnitOfWork:IDisposable 
{
private DbContext context = new DbContext();
私人FooRepository fooRepository;

public FooRepository fooRepository
{
get
{

if(this.fooRepository == null)
{
this.fooRepository = new FooRepository(context);
}
return fooRepository;
}
}

public void Save()
{
context.SaveChanges();
}

private boolwhere = false;

protected virtual void Dispose(bool disposal)
{
if(!this.disposed)
{
if(disposal)
{
context.Dispose();
}
}
this.disposed = true;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}

然后我更改每个存储库以接受上下文

  public class FooRepository:
GenericRepository&Foo>,IFooRepository {

public FooRepository (DbContext context):base(context){}
}


i have used a generic interface and repository in this tugberkugurlu, which is...

public interface IGenericRepository<T> where T : class {

    IQueryable<T> GetAll();
    IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
    void Add(T entity);
    void Delete(T entity);
    void Edit(T entity);
    void Save();
}

and this generic repository

public abstract class GenericRepository<C, T> : 
    IGenericRepository<T> where T : class where C : DbContext, new() {

    private C _entities = new C();
    public C Context {

        get { return _entities; }
        set { _entities = value; }
    }

    public virtual IQueryable<T> GetAll() {

        IQueryable<T> query = _entities.Set<T>();
        return query;
    }

    public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate) {

        IQueryable<T> query = _entities.Set<T>().Where(predicate);
        return query;
    }

    public virtual void Add(T entity) {
        _entities.Set<T>().Add(entity);
    }

    public virtual void Delete(T entity) {
        _entities.Set<T>().Remove(entity);
    }

    public virtual void Edit(T entity) {
        _entities.Entry(entity).State = System.Data.EntityState.Modified;
    }

    public virtual void Save() {
        _entities.SaveChanges();
    }
}

which can now be used like this...

public class FooRepository :
    GenericRepository<FooBarEntities, Foo>, IFooRepository {

    public Foo GetSingle(int fooId) {

        var query = GetAll().FirstOrDefault(x => x.FooId == fooId);
        return query;
    }
}

now, all is, or was well until i had a self referencing entity, like this...

public class Question
    {
        [Key]
        public string QuestionID { get; set; }

        public string QuestionNumber { get; set; }

        public string Message { get; set; }

        public DateTime? DatePosted { get; set; }

        public DateTime? Modified { get; set; }

        public bool HasSubgroups { get; set; }

        public string ApplicationUserId { get; set; }
        [ForeignKey("ApplicationUserId")]
        public virtual ApplicationUser ApplicationUser { get; set; }

        public string PaperID { get; set; }
        [ForeignKey("PaperID")]
        public virtual PaperEntity Paper { get; set; }

        public ICollection<QuestionTag> Tags { get; set; }

        public ICollection<QuestionVote> Votes { get; set; }

        public virtual ICollection<Answer> Answers { get; set; }

        public virtual ICollection<QuestionComment> QuestionComments { get; set; }

        public string ParentQuestionID { get; set; }
        [ForeignKey("ParentQuestionID")]
        public virtual Question QuestionReference { get; set; }
        public virtual ICollection<Question> Questions { get; set; }
    }

and as you can see, my model allows me to have sub-questions to a question. and this is how i try to implement it...

dynamic model = modela;

            string q_id = model.QuestionID.ToString();

            var question = q_id.IsNullOrEmpty() ? null : await questionRepository.FindBy(id => id.QuestionID == q_id);

            if (question == null)
            {
                question = new Question
                {
                    QuestionID = Guid.NewGuid().ToString("D"),
                    QuestionNumber = model.ParentQuestionNumber,
                    PaperID = model.PaperID,
                    Message = model.QuestionTitle,
                    ApplicationUserId = userid,
                    DatePosted = DateTime.UtcNow,
                    Tags = new List<QuestionTag>()
                };

                await questionRepository.Add(question); 
            }

            var questionQuestion = new Question
            {
                QuestionID = Guid.NewGuid().ToString("D"),
                ParentQuestionID = question.QuestionID,
                QuestionNumber = model.QuestionNumber,
                PaperID = question.PaperID,
                Message = model.Message,
                ApplicationUserId = userid,
                DatePosted = DateTime.UtcNow,
                Tags = new List<QuestionTag>()

            };

question.Questions = new List<Question>{questionQuestion};

            await questionRepository.Update(question);
            await questionRepository.Save();

and after i am able to save the first sub-question, the second question throws an error at...

_ctx.Entry(entity).State = EntityState.Modified;

saying...

A first chance exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll

Additional information: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

i have even tried using IDisposable on GenericRepository without luck...Any hint smelling assistance will be highly appreciated...

解决方案

i created a UnitOfWork from this example...

public class UnitOfWork : IDisposable
    {
        private DbContext context = new DbContext();
        private FooRepository fooRepository;

        public FooRepository fooRepository
        {
            get
            {

                if (this.fooRepository == null)
                {
                    this.fooRepository = new FooRepository(context);
                }
                return fooRepository;
            }
        }

        public void Save()
        {
            context.SaveChanges();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }

then i changed each repository to accept a context...

public class FooRepository :
    GenericRepository<Foo>, IFooRepository {

    public FooRepository(DbContext context) : base(context) {}
}

这篇关于实体对象不能由通用存储库中的IEntityChangeTracker的多个实例引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆