2016-09-26 6 views
0

У меня есть проблема с вставкой и обновлением родового Repository, в общей вставке или обновить его hasnot проблемы, но во многих ко многим отношения я получаю сообщение об ошибке при вставке:Insert/Update многие ко многим с Generic Repository

An объект объекта не может ссылаться на несколько экземпляров IEntityChangeTracker.

обновление:

Отношения между этими двумя объектами не может быть определена, так как они присоединены к различным ObjectContext объектов.

мои коды

Интерфейс

public interface IGenericRepository<TEntity>:IDisposable 
    { 
void Insert(TEntity entity); 
void Update(TEntity entity); 
} 

Generic класса

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class 
      { 
       private ApplicationDbContext context=null; 
       private DbSet<TEntity> dbSet=null; 
       public GenericRepository() 
       { 
        this.context = new ApplicationDbContext(); 
        this.dbSet = context.Set<TEntity>(); 
       } 
       public GenericRepository(ApplicationDbContext context) 
       { 
        this.context = context; 
        this.dbSet = context.Set<TEntity>(); 
       } 

       public virtual void Insert(TEntity entity) 
       { 
Error is here---> this.context.Set<TEntity>().Add(entity); 
        // dbSet.Add(entity); 
        context.SaveChanges(); 
       } 

       public virtual void Update(TEntity entity) 
       { 
Error is here---> dbSet.Attach(entity); 
        context.Entry(entity).State = EntityState.Modified; 
        context.SaveChanges(); 
       } 

     } 

и управляющие коды

 private IGenericRepository<Blog> _Repository = null; 
     private IGenericRepository<BlogTag> _RepositoryTag = null; 
     private IGenericRepository<BlogCategory> _RepositoryCategory = null; 

     public BlogsController() 
     { 

      this._Repository = new GenericRepository<Blog>(new DbContext()); 
      this._RepositoryTag = new GenericRepository<BlogTag>(new DbContext()); 
      this._RepositoryCategory = new GenericRepository<BlogCategory>(new DbContext()); 
     } 

    public async Task<ActionResult> Create([Bind(Include = "BlogID,BlogTitle,BlogContent,VisitCount,Preview")] Blog blog 
       ,string[] SelectedTags,string[] SelectedCategories, HttpPostedFileBase files) 
      { 

       if (SelectedTags != null) 
       { 
        blog.BlogTags = new List<BlogTag>(); 
        foreach (var tag in SelectedTags) 
        { 
         var tagToAdd = _RepositoryTag.GetById(int.Parse(tag)); 
         blog.BlogTags.Add(tagToAdd); 
        } 
       } 
       if (SelectedCategories != null) 
       { 
        blog.BlogCategories = new List<BlogCategory>(); 
        foreach (var cat in SelectedCategories) 
        { 
         var catToAdd = _RepositoryCategory.GetById(int.Parse(cat)); 
         blog.BlogCategories.Add(catToAdd); 
        } 
       } 

       if (ModelState.IsValid) 
       { 
        blog.DateTimeInsert = DateTime.UtcNow; 
        blog.DateTimeModify = DateTime.UtcNow; 
        blog.ImagePath= files != null ? Path.GetFileName(files.FileName) : ""; 
        blog.BlogContent = HttpUtility.HtmlEncode(blog.BlogContent); 

        _Repository.Insert(blog); 

        return RedirectToAction("Index"); 
       } 

       ViewBag.BlogTags = new SelectList(_RepositoryTag.Get(), "BlogTagID", "TagName"); 
       ViewBag.BlogCategories = new SelectList(_RepositoryCategory.Get(), "BlogCategoryID", "CategoriesName"); 

       return View(blog); 
      } 


      [HttpPost] 
      [ValidateAntiForgeryToken] 
      public async Task<ActionResult> Edit([Bind(Include = "BlogID,BlogTitle,BlogContent,VisitCount,Preview")] Blog blog 
       , string[] SelectedTags, string[] SelectedCategories, HttpPostedFileBase files) 
      { 

       if (Request["BlogID"] == null) 
       { 
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
       } 
       int id = int.Parse(Request["BlogID"].ToString()); 
       var blogsToUpdate = _Repository.Query(i => i.BlogID == id, null).Include(t => t.BlogTags).Include(t => t.BlogCategories).Single(); 

       if (TryUpdateModel(blogsToUpdate, "", 
        new string[] { "BlogID", "BlogTitle", "BlogContent", "VisitCount","Preview" })) 
       { 
        try 
        { 


         UpdateInstructorCourses(SelectedTags, SelectedCategories, blogsToUpdate); 

         blogsToUpdate.DateTimeModify = DateTime.UtcNow; 
         blogsToUpdate.DateTimeInsert = DateTime.UtcNow; 
         blogsToUpdate.BlogContent = HttpUtility.HtmlEncode(blogsToUpdate.BlogContent); 

         await _Repository.UpdateAsync(blogsToUpdate, d => d.BlogTitle, d => d.VisitCount, d => d.BlogContent, d => d.ImagePath); 

         return RedirectToAction("Index"); 
        } 
        catch (RetryLimitExceededException /* dex */) 
        { 
         //Log the error (uncomment dex variable name and add a line here to write a log. 
         ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator."); 
        } 
       } 
       AssignedDDLCHKBoxValues(blogsToUpdate); 
       return View(blogsToUpdate); 
      } 

      private void UpdateInstructorCourses(string[] SelectedTags, string[] SelectedCategories, Blog blogsToUpdate) 
      { 
       if (SelectedTags == null) 
       { 
        blogsToUpdate.BlogTags = new List<BlogTag>(); 
        return; 
       } 
       if (SelectedCategories == null) 
       { 
        blogsToUpdate.BlogCategories = new List<BlogCategory>(); 
        return; 
       } 

       var SelectedTagsHS = new HashSet<string>(SelectedTags); 
       var SelectedCategoriesHS = new HashSet<string>(SelectedCategories); 
       var blogTags = new HashSet<int>(blogsToUpdate.BlogTags.Select(c => c.BlogTagID)); 

       foreach (var tag in _RepositoryTag.Get()) 
       { 
        if (SelectedTagsHS.Contains(tag.BlogTagID.ToString())) 
        { 
         if (!blogTags.Contains(tag.BlogTagID)) 
         { 
          blogsToUpdate.BlogTags.Add(tag); 
         } 
        }//if 
        else 
        { 
         if (blogTags.Contains(tag.BlogTagID)) 
         { 
          blogsToUpdate.BlogTags.Remove(tag); 
         } 
        }//else 
       }//foreach tag 


       var blogcategories = new HashSet<int> 
        (blogsToUpdate.BlogCategories.Select(c => c.BlogCategoryID)); 
       foreach (var Category in _RepositoryCategory.Get()) 
       { 
        if (SelectedCategoriesHS.Contains(Category.BlogCategoryID.ToString())) 
        { 
         if (!blogcategories.Contains(Category.BlogCategoryID)) 
         { 
          blogsToUpdate.BlogCategories.Add(Category); 
         } 
        }//if 
        else 
        { 
         if (blogcategories.Contains(Category.BlogCategoryID)) 
         { 
          blogsToUpdate.BlogCategories.Remove(Category); 
         } 
        }//else 
       }//foreach skill 
      } 
+0

Если вы в своем коде исключение исключение? Это исключение вызывается, если у вас есть объекты, отслеживаемые разными контекстами, и вы пытаетесь использовать объект контекста через другой. Например, если у вас есть объект A, вставленный в DB через контекст A, а затем создайте объект B, используя контекст B, и свяжите объект A с объектом B и вызовите savechanges в любом контексте, вы получите исключение. – victor

+0

in insert Я получаю ошибку здесь this.context.Set () .Add (entity); и обновите эту строку dbSet.Attach (entity); , я должен упомянуть, что у меня есть 3 экземпляра из 3 тегов репозитория, категории и блога, но я не могу понять, является ли этот объект, который я заполняю, он действителен и без репозитория он работает в любом случае у вас есть предложение, как я могу управлять этим ? – hesam

ответ

0

Ваша проблема заключается в том, что вы используете несколько контекстов для работы с одним объектом. В конструкторе контроллера у вас есть такие строки:

this._Repository = new GenericRepository<Blog>(new DbContext()); 
this._RepositoryTag = new GenericRepository<BlogTag>(new DbContext()); 
this._RepositoryCategory = new GenericRepository<BlogCategory>(new DbContext()); 

Здесь, вы создаете 3 репозитории 9that должны работать вместе) с 3-й различными контекстами.

После этого вы продолжаете читать из RepositoryTag хранилища, здесь:

var tagToAdd = _RepositoryTag.GetById(int.Parse(tag)); 

Когда вы сделаете это, то объект tagToAdd привязывается к контексту внутри RepositoryTag. Если вы отлаживаете свой список BlogTags, где вы добавляете этот tagToAdd, вы увидите, что у вас есть динамический прокси-сервер, что означает, что объект objetc привязан к контексту.

После этого, вы используете другой контекст для заполнения категории хранилища, здесь:

var catToAdd = _RepositoryCategory.GetById(int.Parse(cat)); 
blog.BlogCategories.Add(catToAdd); 

Теперь ваш blog объекта имеет ссылки на 2-й разные контексты: тот, который вы использовали для загрузки метки (RepositoryTag), и тот, который вы использовали для загрузки категории блога (RepositoryCategory).

Наконец, вы пытаетесь INSER blog usgin третьего контекста:

_Repository.Insert(blog); 

Это будет сгенерировано исключение, потому что EF не может работать с несколькими контекстами, как это.

Чтобы решить эту проблему, просто создать экземпляр контекста перед хранилищами, и передать его всем YOUT репозиториев, например:

this.context = new DbContext(); // The context you need to use for all operations you are performing here. 
this._Repository = new GenericRepository<Blog>(this.context); 
this._RepositoryTag = new GenericRepository<BlogTag>(this.context); 
this._RepositoryCategory = new GenericRepository<BlogCategory>(this.context); 

Теперь, не забудьте, что вы должны утилизировать свои контексты. Вот почему наиболее рекомендуемым и распространенным подходом является использование такого кода:

using (var ctx = new DbContext()) { 

    var repo = new GenericRepository<Blog>(ctx); 
    var repoTag = new GenericRepository<BlogTag>(ctx); 
    var repoCategory = new GenericRepository<BlogCategory>(ctx); 

    <the rest of your code where you build the `blog` object> 

    ctx.SaveChanges(); 
} 
+0

спасибо за вашу помощь;), что правильно сейчас работает;) – hesam