2

我是 c# 新手,现在对泛型和实体框架有点困惑。我在数据库中有两个表,我使用实体框架在我的代码中检索它们。在我的 aspx 页面上,我有一个网格,它应该根据用户选择的表填充数据。

将来会有更多的桌子。所以我想写一个工厂模式来获取数据网格的源列表。我不能让它工作,因为我很困惑。

这是我的 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();
    }
} 

有人可以相应地更正代码吗?我必须在这里使用泛型吗?我尝试在 BaseClass 中使用它,但它不能正常工作,因为我必须相应地修复我的子类,对此我一无所知。

4

2 回答 2

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;
}

第三,如果你实现了一个通用的报表库,你不需要编写子类,除非它们有一些特殊的基础没有实现。第四,Filter 方法的当前实现非常糟糕,因为您在这里所做的是从数据库中获取所有记录,然后在内存中过滤它们。这种实现是一种不好的做法。更好的方法是使用 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;
}

所以这是解决您的问题的更好方法。我认为阅读一本名为“More Effective 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);

希望这很有用。

于 2012-06-28T08:11:51.030 回答
0

定义如何显示每个实体类型(或表)的泛型是错误的方法。

相反,使用 MVVM 或 MVC 等模式,根据数据类型(模型)选择视图。

MVVM
MVC
MVC for ASP.NET

于 2012-06-27T15:50:39.233 回答