2012-06-27 2 views
2

Я новичок в C# и теперь немного запутался с Generics и Entity Framework. У меня есть две таблицы в базе данных, которые я извлекаю в своем коде с помощью Entity Framework. На моей странице aspx у меня есть сетка, которая должна заполнять данные на основе того, какой пользователь выбирает таблицу.Confuse with Generics and Entity Framework

В будущем будет больше таблиц. Поэтому я хотел написать шаблон фабрики, чтобы получить исходный список для datagrid. Я не могу заставить его работать, потому что я очень смущен.

Вот мой код для BaseClass и двух дочерних классов.

static class Factory 
{ 
    public static ReportBase GetReport(string name) 
    { 
     switch (name) 
     { 
      case "Child1": 
       return new Child1(); 
      case "Child2": 
       return new Child1(); 
      default: 
       return null; 
     } 
    } 
} 

//Base Class 
class ReportBase<T> 
{ 
    public List<T> _list; 
    public abstract void Load(); 
    public abstract List<T> Filter(DateTime statrtDate, DateTime endDate); 
} 

//Child 1 
class Child1 : ReportBase 
{ 
    public List<GetChild1> _list; 
    public Child1(){} 

    public override void Load() 
    { 
     //GetChild1 is the name of database table 
     var info = from p in Context.GetChild1 select p; 
     _list = info.ToList(); 
    } 

    public List<GetChild1> Filter(DateTime startDate, DateTime endDate) 
    { 
     var filteredValues = from p in _list where p.UploadedDate <= startDate select p; 
     return filteredValues.ToList(); 
    } 
} 

//Child 2 
class Child2 : ReportBase 
{ 
    public List<GetChild2> _list; 
    public Child2() { } 

    public override void Load() 
    { 
     //GetChild2 is the name of database table 
     return (from p in Context.GetChild2 select p).ToList(); 
    } 

    public List<GetChild2> Filter(DateTime startDate, DateTime endDate) 
    { 
     return (from p in _list where p.UploadedDate <= startDate select p).ToList(); 
    } 
} 

Возможно, кто-то исправит код соответствующим образом? Должен ли я использовать Generics здесь? Я попытался использовать его в BaseClass, но он не работает должным образом, потому что мне нужно соответствующим образом исправить мои дочерние классы, для которых у меня нет подсказки.

+0

Я не смотрел на это подробно, но у вас есть опечатка в: "case" Child2 ": return new Child1();" –

ответ

0

Прежде всего, с обобщениями вы можете лучше писать код, который является более читаемым и коротким. Я думаю, что лучше не использовать класс фабрики для хранилищ в конце концов, вы должны знать, какой тип вы имеете дело с ним в вашем коде, такие как:

Child1 report = new Child1(); 
report.SomeBehaviorInChild1(); // this is not achievable with base class. 

Если вы хотите использовать этот завод вы можете выполните следующие действия: ReportBase report = Factory.GetReport();

Во-вторых, это плохая идея, чтобы ваш список был общедоступным, потому что вы не хотите, чтобы те, кто использует ваш класс, создали новый список из своего кода, например: report._list = new List(); Вы не хотите, чтобы это происходило с объектами вашего класса. Поэтому лучше, чтобы ваш список был приватным и зависел только от методов возврата источника данных вашего отчета. приватный список _list;

public List<T> GetDataSource() 
{ 
    return _list; 
} 

В-третьих, если вы реализуете общий reportbase вам не нужно будет писать дочерние классы, если они не имеют что-то особенное, что база не реализует. В-четвертых, текущая реализация метода фильтра является soooo bad, потому что то, что вы здесь делаете, получает все записи из базы данных, а затем фильтрует их в памяти. Эта реализация является плохой практикой. Лучшим подходом является использование IQueryable, который является дефисным объектом выполнения, то есть результат не будет заполнен, пока вы его не попросите.

public List<GetChild1> FilterExample() 
{ 
    IQueryable<GetChild1> result = _context.GetChild1; 
    result = from p in result 
      where p.UploadDate < startDate; 
      select p; 
    //until this moment the query is still not send to the database. 
    result = result.OrderBy(p => p.UploadDate); 

    //when you call the ToList method the query will be executed on the database and the list of filtered and sorted items will be returned. Notice the sorting and filtering is done in the database which is faster than doing it in memory 
    List<GetChild1> populatedResult = result.ToList(); 
    return populatedResult; 
} 

Так что это был лучший подход к вашей проблеме. Я думаю, вам хорошо читать книгу под названием «Более эффективный C# 2008», в которой говорится о запросе и linq в целом. Теперь, если применить это на ваших BaseReportClass мы можем получить следующее:

//Base Class 
class ReportBase<T> where T: class 
{ 
    private DbContext _context; 
    public ReportBase(DbContext context) 
    { 
     _context = context; 
    } 


    //I think GetAll is a more suitable name for your method than load :D 
    public IQueryable<T> GetAll() 
    { 
     return _context.Set<T>(); 
    } 

    public IQueryable<T> Filter(Func<T,bool> filterFunction) 
    { 
     var result = from p in GetAll() 
         where filterFunction(p) 
         select p; 
     return result; 
    } 
} 

Теперь к определению дополнительного поведения для дочерних классов.

//Child 1 
class Child1 : ReportBase<GetChild1> 
{ 
    public ReportBase(DbContext context):base(context) 
    { 

    } 

    public List<GetChild1> FilterOnStartDate(DateTime startDate) 
    { 
     //I don't know if you are familiar with lambda expressions but if you are not you can research it on the internet. 
     //The parameter here is converted into a method that its parameter is "p" of type GetChild1 
     // and the body is "p.UploadDate < startDate". 
     // Note you can remove the type of the parameter because the compiler can predict it. 
     return Filter((GetChild1 p) => p.UploadDate < startDate).ToList(); 
    } 
} 

Это код, который использует классы:

Child1 report = new Child1(new GetChild1Entities()); 
report.FilterOnStartDate(DateTime.Now); 

Надежда это было полезно.

+0

Привет, Манар, спасибо! Одна вещь, однако, в моем методе загрузки, я уже сохранил записи в памяти, переведя ее в список и сохранив в частном локальном списке. В фильтре тогда я запрашиваю локальный список, а не базу данных, так что это не так плохо или я чего-то не хватает? В моем случае, чтобы повысить производительность, я пытаюсь загрузить содержимое, когда запускаются события Application_Start, а затем я храню данные в памяти, если пул приложений не перерабатывается ночью. Есть лучший способ сделать это. Является ли Entity Framework достаточно робостью для такой работы? Еще раз спасибо .. действительно appereciated. – user1485190

+0

Привет. Как дела? Есть что-то неправильно с получением всех данных и помещением их в память, поскольку по мере того, как данные становятся более крупными, получая данные и помещая их в память, на сервере приложений будет использоваться больше памяти, что скажется на производительности вашего сайта. Поэтому лучше фильтровать данные в базе данных и получать из нее только необходимые данные. –

0

Дженерики для определения того, как отображать каждый тип сущности (или таблицы), являются неправильным подходом.

Вместо этого используйте шаблон, такой как MVVM или MVC, где в соответствии с типом данных (модель) вы выбираете представление.

MVVM
MVC
MVC for ASP.NET

+0

Я уже реализую MVC, поэтому вы не видите какой-либо материал в моих классах, который я разместил выше. нормально, дженерики могут быть не apporach здесь, а как я получаю объект моих дочерних классов на моей фабрике? Что я должен писать в своем базовом классе? Было бы здорово, если бы кто-то мог исправить эти классы, чтобы я мог понять больше. Спасибо хоть. – user1485190

+0

Используйте фабрику или еще лучше - отражение, чтобы выбрать правильный класс представления (например, правильный класс отчета) для каждого класса модели. Один из подходов состоит в том, чтобы использовать словарь класса модели для просмотра класса (который вы можете сериализовать и десериализовать из xml), чтобы найти правильный класс представления, а затем создать его экземпляр. –