我在这个tugberkugurlu中使用了通用接口和存储库,这是......
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();
}
和这个通用存储库
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();
}
}
现在可以像这样使用......
public class FooRepository :
GenericRepository<FooBarEntities, Foo>, IFooRepository {
public Foo GetSingle(int fooId) {
var query = GetAll().FirstOrDefault(x => x.FooId == fooId);
return query;
}
}
现在,直到我有了一个自引用实体,就像这样......或者很好......
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; }
}
正如您所看到的,我的模型允许我对一个问题提出子问题。这就是我试图实现它的方式......
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();
并且在我能够保存第一个子问题之后,第二个问题在......
时抛出错误_ctx.Entry(entity).State = EntityState.Modified;
说...
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.
我甚至尝试在IDisposable
上使用GenericRepository
但没有运气......任何暗示嗅觉的帮助都将受到高度赞赏......
答案 0 :(得分:1)
我想你因为背景而有问题。可能你有两个同一个实体的背景。这可能是因为创建了require 'test_helper'
class StaticPagesControllerTest < ActionController::TestCase
def setup
@base_title = "Ruby on Rails Tutorial Sample App"
end
test "should get home" do
get :home
assert_response :success
assert_select "title", "Ruby on Rails Tutorial Sample App" end
test "should get help" do
get :help
assert_response :success
assert_select "title", "Help | #{@base_title}"
end
test "should get about" do
get :about
assert_response :success
assert_select "title", "About | #{@base_title}"
end
test "should get contact" do
get :contact
assert_response :success
assert_select "title", "Contact | #{@base_title}"
end
end
。尝试使用context-per-repository
pattern,或者只为所有存储库创建一个上下文。
答案 1 :(得分:1)
我从this example ...
创建了一个UnitOfWorkpublic 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);
}
}
然后我改变了每个存储库以接受上下文......
public class FooRepository :
GenericRepository<Foo>, IFooRepository {
public FooRepository(DbContext context) : base(context) {}
}