Ich weiß, ich bin sehr spät zu diesem, aber dies ist etwas, das eine Menge Entwickler Gesicht whiles Entwicklung Multi-Thread-Anwendung mit Entity Framework und wpf. Hier sind ein paar Dinge, die Sie beachten müssen
- ) können Sie vom Hintergrund-Thread nicht auf den UI-Thread zugreifen.
- ) Dbcontext ist nicht thread-sicher, so dass die Verwendung in einem Multithreading in einer Multi-Thread-Umgebung zu Problemen führen kann, wenn nicht darauf geachtet wird
Hier ist also die Art und Weise, wie ich dieses Problem gelöst habe: Meine Lösung folgt dem abstrakten Repository-Muster. Die beteiligten Klassen und Schnittstellen sind:
-
DataRepository und IDataRepository
-
Student und IStudent
-
StudentViewModel
-
EntityBase
Dies ist IDataRepository
public interface IDataRepository
{
void AddAsync<T>(T entity, Action<T>callBack,Action<Exception>exceptionCallback=null) where T : EntityBase;
void DeleteAsync<T>(int[] ids, Action callBack, Action<Exception> exceptionCallback = null) where T : EntityBase;
void UpdateAsync<T>(T entity, Action<T> callBack, Action<Exception> exceptionCallback = null) where T : EntityBase;
void FindAsync<T>(int id, Action<T> callBack, Action<Exception> exceptionCallback = null) where T : EntityBase;
void FindAsync<T>(Action<List<T>> callBack,Expression<Func<T, bool>> predicate=null, int? pageIndex=0, int? pageSize=20, params Expression<Func<T, object>>[] includes) where T : EntityBase;
}
Dies ist DataRepository
public class Repository<TContext>: IDataRepository
where TContext:DbContext,new ()
{
protected static void ExecuteAsync<T>(Func<List<T>> task, Action<List<T>> callback, Action<Exception> exceptionCallback = null) where T : EntityBase
{
var worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
e.Result = task();
};
worker.RunWorkerCompleted += (s, e) =>
{
if (e.Error == null && callback != null)
callback((List<T>)e.Result);
else if (e.Error != null && exceptionCallback != null)
exceptionCallback(e.Error);
};
worker.RunWorkerAsync();
}
protected static void ExecuteAsync<T>(Func<T> task, Action<T> callback, Action<Exception> exceptionCallback = null) where T : EntityBase
{
var worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
e.Result = task();
};
worker.RunWorkerCompleted += (s, e) =>
{
if (e.Error == null && callback != null)
callback((T)e.Result);
else if (e.Error != null && exceptionCallback != null)
exceptionCallback(e.Error);
};
worker.RunWorkerAsync();
}
protected static void ExecuteAsync(Action task, Action callback, Action<Exception> exceptionCallback = null)
{
var worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
task();
};
worker.RunWorkerCompleted += (s, e) =>
{
if (e.Error == null && callback != null)
callback();
else if (e.Error != null && exceptionCallback != null)
exceptionCallback(e.Error);
};
worker.RunWorkerAsync();
}
public void AddAsync<T>(T entity, Action<T> callBack, Action<Exception> exceptionCallback = null) where T : EntityBase
{
ExecuteAsync(() =>
{
using (var context = new TContext())
{
var addedEntity = context.Set<T>().Add(entity);
context.SaveChanges();
return addedEntity;
}
},callBack,exceptionCallback);
}
public void DeleteAsync<T>(int[] ids, Action callBack, Action<Exception> exceptionCallback = null) where T : EntityBase
{
ExecuteAsync(() =>
{
using (var context = new TContext())
{
var entitiesToRemove = context.Set<T>().Where(x => ids.Contains(x.Id)).ToList();
foreach (var entity in entitiesToRemove)
{
context.Entry(entity).State=EntityState.Deleted;
}
context.SaveChanges();
}
},callBack, exceptionCallback);
}
public void UpdateAsync<T>(T entity, Action<T> callBack, Action<Exception> exceptionCallback = null) where T : EntityBase
{
ExecuteAsync(() =>
{
using (var context=new TContext())
{
context.Entry(entity).State=EntityState.Modified;
context.SaveChanges();
var updatedEntity = context.Set<T>().Find(entity.Id);
return updatedEntity;
}
},callBack,exceptionCallback);
}
public void FindAsync<T>(int id, Action<T> callBack, Action<Exception> exceptionCallback = null) where T : EntityBase
{
ExecuteAsync(() =>
{
using (var context=new TContext())
{
var entity = context.Set<T>().Find(id);
return entity;
}
},callBack,exceptionCallback);
}
public void FindAsync<T>(Action<List<T>> callBack, Expression<Func<T, bool>> predicate=null, int? pageIndex = 0, int? pageSize = 20, params Expression<Func<T, object>>[] includes) where T : EntityBase
{
ExecuteAsync(() =>
{
using (var context=new TContext())
{
var query = context.Set<T>().AsQueryable();
if (includes != null)
{
query = includes.Aggregate(query, (current, include) => current.Include(include));
}
if (predicate != null)
query = query.Where(predicate);
var offset = (pageIndex ?? 0) * (pageSize ?? 15);
query = query.OrderBy(x=>x.Id).Skip(offset).Take(pageSize ?? 15);
return query.ToList();
}
},callBack);
}
}
dies ist das Student Repository und IStudentRepository
public interface IStudentRepository:IDataRepository
{
void AddGuardian(Gurdian gurdian, int studentId,Action<Student> callBack);
void SaveStudent(Student student, Gurdian gurdian,Action<Student>callBack);
void GetPrimaryGurdian(int studentId,Action<Gurdian> callBack );
}
[Export(typeof(IStudentRepository))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class StudentRepository : Repository<StudentContext>, IStudentRepository
{
public void AddGuardian(Gurdian gurdian, int studentId, Action<Student> callBack)
{
FindAsync<Student>(studentId, (student) =>
{
student.Gurdians.Add(gurdian);
UpdateAsync(student, callBack);
});
}
public void SaveStudent(Student student, Gurdian gurdian, Action<Student> callBack)
{
student.Gurdians.Add(gurdian);
AddAsync(student, callBack);
}
public void GetPrimaryGurdian(int studentId, Action<Gurdian> callBack)
{
FindAsync<Student>(studentId,(student)=> { callBack(student.PrimaryGurdian); });
}
}
Dann schließlich Ihr viewModel
[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
public class StudentViewModel : ViewModelBase
{
private readonly IStudentRepository _repository;
[ImportingConstructor]
public StudentViewModel()
{
_repository =new StudentRepository();
Student = new Student();
SaveStudentCommand = new RelayCommand(OnStudentSaveExcute, CanSaveStudent);
}
#region Properties
private Student _student;
public Student Student
{
get { return _student; }
set { _student = value; OnPropertyChanged(() => Student); }
}
private ObservableCollection<Student> _students = new ObservableCollection<Student>();
public ObservableCollection<Student> Students
{
get { return _students; }
set { _students = value; }
}
#endregion
#region Commands
public ICommand SaveStudentCommand { get; set; }
private void OnStudentSaveExcute()
{
_repository.SaveStudent(Student,Gurdian, (student) =>
{
_students.Add(student);
});
}
#endregion
private void LoadStudents()
{
_repository.FindAsync<Student>((students) =>
{
foreach(var student in students)
_students.Add(student);
});
}
}
public class EntityBase{
public int get{get;set;}
}