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...
then i changed each repository to accept a context...
I suppose u have problem because of contexts. Probably u have two contexts with the same entity. It can be because of creating
context-per-repository
. Try to useUnitOfWork
pattern, or just create one context for all repositories.