Я собираюсь начать новый веб-проект asp.net и собираюсь перейти на LINQ-to-SQL. Я проделал небольшую работу по настройке уровня данных, используя некоторую информацию, которую я нашел с помощью Майк Хэдлоу, которая использует интерфейс и обобщения для создания репозитория для каждой таблицы в базе данных. Сначала я подумал, что это интересный подход. Однако теперь я думаю, что было бы разумнее создать базовый класс Repository и наследовать от него, чтобы создать класс TableNameRepository для таблиц, к которым мне нужно получить доступ.
Какой подход позволит мне добавить функциональность, специфичную для таблицы, чистым тестируемым способом? Вот моя реализация репозитория для справки.
public class Repository<T> : IRepository<T> where T : class, new()
{
protected IDataConnection _dcnf;
public Repository()
{
_dcnf = new DataConnectionFactory() as IDataConnection;
}
// Constructor injection for dependency on DataContext
// to actually connect to a database
public Repository(IDataConnection dc)
{
_dcnf = dc;
}
/// <summary>
/// Return all instances of type T.
/// </summary>
/// <returns>IEnumerable<T></returns>
public virtual IEnumerable<T> GetAll()
{
return GetTable;
}
public virtual T GetById(int id)
{
var itemParam = Expression.Parameter(typeof(T), "item");
var whereExp = Expression.Lambda<Func<T, bool>>
(
Expression.Equal(
Expression.Property(itemParam, PrimaryKeyName),
Expression.Constant(id)
), new ParameterExpression[] { itemParam }
);
return _dcnf.Context.GetTable<T>().Where(whereExp).Single();
}
/// <summary>
/// Return all instances of type T that match the expression exp.
/// </summary>
/// <param name = "exp"></param>
/// <returns>IEnumerable<T></returns>
public virtual IEnumerable<T> FindByExp(Func<T, bool> exp)
{
return GetTable.Where<T>(exp);
}
/// <summary>See IRepository.</summary>
/// <param name = "exp"></param><returns></returns>
public virtual T Single(Func<T, bool> exp)
{
return GetTable.Single(exp);
}
/// <summary>See IRepository.</summary>
/// <param name = "entity"></param>
public virtual void MarkForDeletion(T entity)
{
_dcnf.Context.GetTable<T>().DeleteOnSubmit(entity);
}
/// <summary>
/// Create a new instance of type T.
/// </summary>
/// <returns>T</returns>
public virtual T Create()
{
//T entity = Activator.CreateInstance<T>();
T entity = new T();
GetTable.InsertOnSubmit(entity);
return entity;
}
/// <summary>See IRepository.</summary>
public virtual void SaveAll()
{
_dcnf.SaveAll();
}
#region Properties
private string PrimaryKeyName
{
get { return TableMetadata.RowType.IdentityMembers[0].Name; }
}
private System.Data.Linq.Table<T> GetTable
{
get { return _dcnf.Context.GetTable<T>(); }
}
private System.Data.Linq.Mapping.MetaTable TableMetadata
{
get { return _dcnf.Context.Mapping.GetTable(typeof(T)); }
}
private System.Data.Linq.Mapping.MetaType ClassMetadata
{
get { return _dcnf.Context.Mapping.GetMetaType(typeof(T)); }
}
#endregion
}
Четко сформулируйте свой вопрос, иначе он будет закрыт как «не настоящий вопрос».





Я был бы склонен предположить, что используете ли вы конкретные типы или нет, не имеет значения, как если бы вы использовали инъекцию зависимостей (замок?) Для создания репозиториев (чтобы вы могли обернуть их разными кешами и т. д.), Тогда ваша кодовая база будет никто не станет мудрее, каким бы способом вы это ни сделали.
Тогда просто попросите своего DI предоставить репозиторий. Например. для замка:
public class Home {
public static IRepository<T> For<T> {
get {
return Container.Resolve<IRepository<T>>();
}
}
}
Лично я бы не стал отказываться от типов, пока вы не обнаружите в этом необходимость.
Я предполагаю, что вторая половина вашего вопроса заключается в том, можете ли вы легко предоставить реализацию IRepository в памяти для целей тестирования и кеширования. Для этого я хотел бы следить, как linq-to-objects может быть медленным, и вы можете найти что-то вроде http://www.codeplex.com/i4o полезным.
Не следует создавать репозиторий для каждой таблицы. Вместо этого вы должны создать репозиторий для каждого «корня сущности» (или совокупного корня), который существует в вашей модели предметной области. Вы можете узнать больше о шаблоне и увидеть рабочий пример здесь:
Вы не задаете конкретный вопрос.