2013-11-14 2 views
2

У меня есть код EF для извлечения некоторых объектов в контроллере, но я хочу отделить свои функции, чтобы улучшить повторное использование кода.Могу ли я передать контекст 'using' другому методу в C#?

Мой код в настоящее время выглядит следующим образом:

public ActionResult SentMessages(){ 
    MyModel model = new MyModel(); 
    int user_id = GetCurrentUserId(); 
    using(DataContext db = new DataContext()){ 
     model.Messages = 
       db.Messages 
       .Where(x => x.sent == true) 
       .Where(x => x.user_id == user_id) 
       .Where(x => x.date_deleted == null) 
       .OrderBy(x => x.date_sent) 
       .Take(10) 
       .ToList(); 
     model.Groups = db.Groups 
       .Where(x => x.user_id == user_id) 
       .Where(x => x.date_deleted == null) 
       .OrderBy(x => x.date_created) 
       .ToList(); 
    } 
    return model; 
} 

Я хочу, чтобы разбить его на многоразовые куски кода, (и делают мои контроллеры меньше), как так

public ActionResult SentMessages(){ 
    MyModel model = new MyModel(); 
    int user_id = GetCurrentUserId(); 
    model.Messages = GetLastTenMessages(user_id); 
    model.Groups = GetGroups(user_id); 
    return model; 
} 

public static List<Message> GetLastTenMessages(int user_id){ 
    using(DataContext db = new DataContext()){ 
     return db.Messages 
       .Where(x => x.sent == true) 
       .Where(x => x.user_id == user_id) 
       .Where(x => x.date_deleted == null) 
       .OrderBy(x => x.date_sent) 
       .Take(10) 
       .ToList(); 
    } 
} 

public static List<Group> GetGroups(int user_id){   
    using(DataContext db = new DataContext()){ 
     return db.Groups 
       .Where(x => x.user_id == user_id) 
       .Where(x => x.date_deleted == null) 
       .OrderBy(x => x.date_created) 
       .ToList(); 
    } 
} 

Однако, это приводит к два отдельных подключения к базе данных (насколько я понимаю). Один открывается и закрывается для каждого запроса.

Есть ли способ, чтобы передать контекст методу, что-то вроде этого

public ActionResult SentMessages(){ 
    MyModel model = new MyModel(); 
    int user_id = GetCurrentUserId(); 
    using(DataContext db = new DataContext()){ 
     model.Messages = GetLastTenMessages(user_id, db); 
     model.Groups = GetGroups(user_id, db); 
    } 
    return model; 
} 

public static List<Message> GetLastTenMessages(int user_id, DataContext db){ 
     return db.Messages 
       .Where(x => x.sent == true) 
       .Where(x => x.user_id == user_id) 
       .Where(x => x.date_deleted == null) 
       .OrderBy(x => x.date_sent) 
       .Take(10) 
       .ToList(); 
} 

public static List<Group> GetGroups(int user_id, DataContext db){   
     return db.Groups 
       .Where(x => x.user_id == user_id) 
       .Where(x => x.date_deleted == null) 
       .OrderBy(x => x.date_created) 
       .ToList(); 
} 

Есть ли что-то подобное, я могу сделать так, что я могу и выделить свой код, а также использовать минимальное количество возможно ли подключение к базе данных?

+0

первая реализация вызывает также 2 запросов к БД – Nagg

+4

Кажется, вы написали Раствора себя, что не так ли? – SergeyS

+0

Означает ли это два отдельных соединения с базой данных или оба запроса выполняются под тем же соединением в примере 3? (@nagg, вот что я имел в виду - два _connections_, а не запросы) – roryok

ответ

2

Сначала я двигался в направлении класса обслуживания. Таким образом, вы могли бы иметь новый класс вроде этого:

public class UserService 
{ 

private DataContext _db; 
//private int _user_id 

public UserService(DataContext db) 
{ 
    _db = db 
    //perhaps it would be better to get the user id here 
    //rather than pass it in to the methods as a parameter 
    //_user_id = GetCurrentUserId(); 
    //or maybe put HttpContext into DataContext and do this: 
    //_user_id = db.GetCurrentUserId(); 
} 

private List<Message> GetLastTenMessages(int user_id){ 
     return _db.Messages 
       .Where(x => x.sent == true) 
       .Where(x => x.user_id == user_id) 
       .Where(x => x.date_deleted == null) 
       .OrderBy(x => x.date_sent) 
       .Take(10) 
       .ToList(); 
} 

private List<Group> GetGroups(int user_id){   
     return _db.Groups 
       .Where(x => x.user_id == user_id) 
       .Where(x => x.date_deleted == null) 
       .OrderBy(x => x.date_created) 
       .ToList(); 
} 

public MyModel GetSentMessages(int user_id) 
{ 
     MyModel model = new MyModel(); 
     model.Messages = GetLastTenMessages(user_id, db); 
     model.Groups = GetGroups(user_id, db); 
     return model 
    } 
} 
} 

Тогда ваш контроллер будет выглядеть следующим образом

public ActionResult SentMessages(){ 
    using(DataContext db = new DataContext()){ 
     var us = new UserService(db); 
     return View(us.GetSentMessages(GetCurrentUserId())); 
    } 
} 

Тогда я хотел бы посмотреть, чтобы ввести репозитории для доступа к данным. UserService затем перейти на что-то вроде этого:

public class UserService 
{ 
    public UserService(DataContext db) 
    { 
     _db = db; 
     _msgRepo = new MessageRepository(_db.Messages); 
     _groupsRepo = new GroupsRepository(_db.Groups); 
    } 

    public MyModel GetSentMessages() 
    { 
      MyModel model = new MyModel(); 
      model.Messages = _msgRepo.GetLastTenMessages(db.user_id); 
      model.Groups = _groupsRepo.GetGroups(db.user_id); 
      return model 
     } 
    } 
} 

Тогда я думаю о обертывание DbContext в моем собственном UnitOfWork классе. UserService затем перейти на что-то вроде этого:

public class UserService 
{ 
    private UnitOfWork _uow; 

    public UserService(UnitOfWork uow) 
    { 
     _uow = uow; 
    } 

    public MyModel GetSentMessages() 
    { 
      MyModel model = new MyModel(); 
      model.Messages = _uow.MessageRepo.GetLastTenMessages(); 
      model.Groups = _uow.GroupRepo.GetGroups(); 
      return model 
     } 
    } 

И контроллер будет мигрировать к этому:

private UnitOfWork _uow; 

public UserController(UnitOfWork uow) 
{ 
    _uow = uow; 
    _us = new UserService(_uow); 
} 

public ActionResult SentMessages() 
{ 
    return View(us.GetSentMessages());  
} 

protected override void Dispose(bool disposing) 
{ 
    if (disposing) 
     _uow.Dispose(); 
    base.Dispose(disposing); 
} 
+0

Я думаю, что ошибка в том, что первый код контроллера не должен возвращать us.GetSentMessages (GetCurrentUserId()); 'be' return View (us.GetSentMessages (GetCurrentUserId())); '? Я не думал о создании всей модели на уровне сервиса, что сделало бы мои контроллеры намного меньшими. – roryok

+0

Да, возможно, это должно произойти. Я просто скопировал код из вопроса и не заметил этого. На самом деле я не уверен, лучше ли отображение в ViewModels на уровне обслуживания или контроллере. Это зависит от вас на самом деле ... – Colin

Смежные вопросы