Я сделал учебники по множеству вопросов о единицах работы и шаблонах репозитория. Я пытаюсь соединить два в реализации MVC и Ef4. Учебник имеет небольшую модель EF, всего 2 объекта. Таким образом, объекты, соответствующие двум объектам, были определены с помощью ICollections для свойств навигации и т. Д., Как и в первом коде, но не было связи между этими объектами и структурой объектов. Это объекты, которые были объединены как хранилища в единицу работы. Но здесь я начинаю задавать следующие вопросы.
- Зачем создавать в основном дубликаты объектов из объектов, уже находящихся в каркасе сущностей, когда вы можете использовать объекты в каркасе сущностей? Вы не можете?
- Если я создаю эти объекты ... мне нужно отобразить всю модель ef? Имея ICollections для свойств навигации, я получаю ошибки, если объекты не совпадают точно, и это в основном продолжает каскадироваться на протяжении большей части модели. Модель довольно большая и включает в себя более десятка объектов, и мне не нужно создавать объекты, которые не будут использоваться в хранилище.
- Если это классы, которые вы отправляете в свои представления ... разве классы моделей представлений не должны быть урезаны версиями ваших реальных классов моделей? Это означало бы, что в моем контроллере я использовал бы единицы работы и классы репозитория для извлечения данных, а затем также разбирал их и передавал только определенные фрагменты данных в модель представления. Это означает, что вся та чистота, которую мы только что получили, используя шаблоны единиц работы и хранилища, теперь начинает исчезать.
У меня есть следующий код ...
namespace Data
{
public interface IRepository<T>
where T : class//, IEntity
{
IQueryable<T> FindAll();
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
//T FindById(int id);
void Add(T newEntity);
void Remove(T entity);
}
public class SqlRepository<T> : IRepository<T>
where T : class//, IEntity
{
public SqlRepository(ObjectContext context)
{
_objectSet = context.CreateObjectSet<T>();
}
public IQueryable<T> Find(Expression<Func<T, bool>> predicate)
{
return _objectSet.Where(predicate);
}
public void Add(T newEntity)
{
_objectSet.AddObject(newEntity);
}
public void Remove(T entity)
{
_objectSet.DeleteObject(entity);
}
public IQueryable<T> FindAll()
{
return _objectSet;
}
protected ObjectSet<T> _objectSet;
}
}
public class SqlUnitOfWork : IUnitOfWork
{
public SqlUnitOfWork()
{
var connectionString =
ConfigurationManager
.ConnectionStrings[ConnectionStringName]
.ConnectionString;
_context = new ObjectContext(connectionString);
_context.ContextOptions.LazyLoadingEnabled = true;
}
public IRepository<Domain.Project> Projects
{
get
{
if (_projects == null)
{
_projects = new SqlRepository<Domain.Project>(_context);
}
return _projects;
}
}
public void Commit()
{
_context.SaveChanges();
}
SqlRepository<Domain.Project> _projects = null;
//SqlRepository<TimeCard> _timeCards = null;
readonly ObjectContext _context;
const string ConnectionStringName = "Entities";
}
}
namespace Domain
{
public interface IRepository<T>
where T : class//, IEntity
{
IQueryable<T> FindAll();
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
//T FindById(int id);
void Add(T newEntity);
void Remove(T entity);
}
public interface IUnitOfWork
{
IRepository<Project> Projects { get; }
//IRepository<TimeCard> TimeCards { get; }
void Commit();
}
}
и затем я объявил свои доменные классы следующим образом ... также в пространстве имен домена.
public class Project //: IEntity
{
public virtual int ProjectId { get; set; }
public virtual int UserId { get; set; }
public virtual int CategoryId { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
// nav prop - do I have to have these?
public virtual ICollection<Image> Images { get; set; }
public virtual ICollection<WatchedProject> WatchedProjects { get; set; }
public virtual ICollection<RequestForProposal> RequestForProposals { get; set; }
public virtual ICollection<Message> Messages { get; set; }
public virtual Category Category { get; set; }
}
Сейчас я просто тестирую это, и у меня есть следующий код консольного приложения ...
static void Main(string[] args)
{
IUnitOfWork _unitOfWork = new SqlUnitOfWork();
IRepository<Domain.Project> _repository = _unitOfWork.Projects;
var prjs = _unitOfWork.Projects.FindAll( );
foreach (Domain.Project prj in prjs)
{
Console.WriteLine(prj.Description);
}
Console.Read();
}
но когда я запускаю эту строку
IRepository<Domain.Project> _repository = _unitOfWork.Projects;
до ...
_objectSet = context.CreateObjectSet<T>();
и я получаю следующее исключение ...
System.Data.MetadataException was unhandled
Message=Schema specified is not valid. Errors:
The relationship 'Model.fk_projects_catetegoryid_categories' was not loaded because the type 'Model.Category' is not available.
The following information may be useful in resolving the previous error:
The required property 'ServiceProviderCategories' does not exist on the type 'Domain.Category'.
The relationship 'Model.FK_Messages_Projects_ProjectId' was not loaded because the type 'Model.Message' is not available.
The following information may be useful in resolving the previous error:
The required property 'MessageId' does not exist on the type 'Domain.Message'.
The relationship 'Model.fk_requestforproposals_projectid_projects' was not loaded because the type 'Model.RequestForProposal' is not available.
The following information may be useful in resolving the previous error:
The required property 'Project' does not exist on the type 'Domain.RequestForProposal'.
The relationship 'Model.FK_WatchedProject_ProjectId_Projects' was not loaded because the type 'Model.WatchedProject' is not available.
The following information may be useful in resolving the previous error:
The required property 'WatchedProjectId' does not exist on the type 'Domain.WatchedProject'.
The relationship 'Model.ProjectImage' was not loaded because the type 'Model.Image' is not available.
The following information may be useful in resolving the previous error:
The required property 'ImageId' does not exist on the type 'Domain.Image'.
Source=System.Data.Entity
StackTrace:
at System.Data.Metadata.Edm.ObjectItemCollection.LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly, Boolean loadReferencedAssemblies, EdmItemCollection edmItemCollection, Action`1 logLoadMessage)
at System.Data.Metadata.Edm.ObjectItemCollection.ImplicitLoadAssemblyForType(Type type, EdmItemCollection edmItemCollection)
at System.Data.Metadata.Edm.MetadataWorkspace.ImplicitLoadAssemblyForType(Type type, Assembly callingAssembly)
at System.Data.Objects.ObjectContext.GetTypeUsage(Type entityCLRType)
at System.Data.Objects.ObjectContext.GetEntitySetFromContainer(EntityContainer container, Type entityCLRType, String exceptionParameterName)
at System.Data.Objects.ObjectContext.GetEntitySetForType(Type entityCLRType, String exceptionParameterName)
at System.Data.Objects.ObjectContext.CreateObjectSet[TEntity]()
at Data.SqlRepository`1..ctor(ObjectContext context) in C:\Projects\TestProjectClasses\Data\SqlRepository.cs:line 18
at Data.SqlUnitOfWork.get_Projects() in C:\Projects\TestProjectClasses\Data\SqlUnitOfWork.cs:line 31
at TestProjectClasses.Program.Main(String[] args) in C:\Projects\TestProjectClasses\TestProjectClasses\Program.cs:line 26
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Я получаю это исключение, потому что эти объекты не были созданы в моем пространстве имен домена ... но я не хочу создавать копии каждого объекта. Я сделал некоторые исследования, но все исследования. Но кажется, что мне нужно в какой-то момент преобразовать эти объекты ... есть ли лучший способ сделать это, чем поместить кучу логики преобразования в код вашего контроллера?