Проблема абстрагирования архитектуры в репозитории ASP.NET MVC - PullRequest
0 голосов
/ 21 января 2010

Я работаю с MVC ASP.NET 3.5 SP1 на VS2008.
Я ищу способ абстрагировать эти три метода, которые есть в моем хранилище Users.

public User GetUser(Log log)
{
  return db.Users.FirstOrDefault(u => u.Logs.Any(l => l.id.Equals(log.id)));
}

public User GetUser(Product product)
{
  return db.Users.FirstOrDefault(u => u.Products.Any(pr => pr.id.Equals(product.id)));
}

public User GetUser(Photo photo)
{
  return db.Users.FirstOrDefault(u => u.Photos.Any(ph => ph.id.Equals(photo.id)));
}

Мой DB.edmx содержит модели

User    [id, username, ...]  
Product [id, name, ...]
Photo   [id, name, ...]
Log     [id, data, ...]

Возможно ли иметь только ONE метод для всех этих (и будущих) методов, основанных на поиске model.id?

Ответы [ 3 ]

0 голосов
/ 21 января 2010

Если все связанные объекты (Журнал, Продукт и Фотография) будут искать по общему свойству (id INT), возможно, вы могли бы попробовать что-то вроде этого ...

Сначала создайте интерфейс:

public interface IUserAssociation
{
    int id { get; }
}

Тогда каждый из трех классов будет реализовывать этот интерфейс следующим образом:

public partial class Product : IUserAssociation
{
}

Метод GetUser будет выглядеть так:

public User GetUser<T>(T entity) where T : IUserAssociation
{
    var type = typeof(T);
    if (type == typeof(Log))
    {
        return db.Users.FirstOrDefault(u => u.Logs.Any(l => l.id.Equals(entity.id)));
    }
    else if (type == typeof(Product))
    {
        return db.Users.FirstOrDefault(u => u.Products.Any(pr => pr.id.Equals(entity.id)));
    }
    else if (type == typeof(Photo))
    {
        return db.Users.FirstOrDefault(u => u.Photos.Any(ph => ph.id.Equals(entity.id)));
    }
    else
    {
        throw new ArgumentException();
    }
}

Тогда вы сможете вызвать GetUser и передать ему сущность Log, Photo или Product из одного метода. Это не очень элегантно, но подойдет для этой конкретной ситуации.

0 голосов
/ 21 января 2010

Мне больше нравится решение Крейга, но я бы предложил это:

Repository.GetUser(u => u.Logs, log);

Что будет возможно, если все ваши сущности будут производными от

public interface IEntity { public int Id { get; } }

Тогда метод будет похож на

public User GetUser<T, Y>(Func<T, IList<Y>> getlist, Y sample)
   where T: IEntity
   where Y: IEntity
{
  return db.Users.Select(x => getlist(x).Any(y => y.Id == sample.Id)).FirstOrDefault();
}

Также, если мы возьмем идею S # arp Architecture, что если entity1.Id == entity2.Id (для постоянных сущностей), то Equals (entity1, entity2) - мы можем использовать getlist (x) .Contains (sample).

0 голосов
/ 21 января 2010
public User GetUser(Expression<Func<User, bool>> restriction)
{
  return db.Users.Where(restriction).FirstOrDefault();
}

Теперь используйте это:

var u = Repository.GetUser(u => u.Logs.Any(l => l.id.Equals(log.id)));

Вы также можете использовать MS DynamicQuery :

using System.Linq.Dynamic;

//...
public User GetUser(string propertyName, int id)
{
    var restriction = propertyName + ".Any(id = @0)";
    return db.Users.Where(restriction, id).FirstOrDefault();
}

var u = Repository.GetUser("Logs", log.id);

Возможно, у меня не совсем правильный синтаксис, но вы поняли.

...