将平面DB模型映射到OO模型

时间:2011-04-22 21:20:43

标签: c# oop

下面的代码详细描述了我的设计问题。我在数据库中有一个任务表,可以有不同类型的重复发生模式。任务表具有每个可能的重复模式字段的列。但是,我希望Task对象根据db中的模式创建正确的模式。下面的代码将完成此操作,但问题是调用代码将始终检查在执行任何操作之前返回的重复类型。

e.g。

var t = new Task();
var pattern = t.Recurrance;

调用代码不知道正在创建什么类型的重复?

对此进行建模的更好方法是什么?

class Task
{
    private int recurrenceType = 0; //pulled from the db
    public Task()
    {
        //determine recurrence type from database 
        switch (recurrenceType)
        {
            case 0:
                Recurrance = new RecurrenceDaily();
                break;
            case 1:
                Recurrance = new RecurrenceMonthly();
                break;
            case 2:
                Recurrance = new RecurrenceWeekly();
                break;
        }
    }
    public RecurrenceBase Recurrance { get; set;}
}

abstract class RecurrenceBase
{
    public int Frequency { get; set; }
}

class RecurrenceDaily : RecurrenceBase
{
    public bool Weekends { get; set; }
}

class RecurrenceWeekly : RecurrenceBase
{
    public DaysOfWeekFlagsEnum DaysOfWeek { get; set; }
}

class RecurrenceMonthly : RecurrenceBase
{
    public byte DayOfMonth { get; set; }
    public WeekEnum Week { get; set; }
    public DayOfWeekEnum DayOfWeek { get; set; }
}

4 个答案:

答案 0 :(得分:0)

嗯,您在此代码中遇到了许多问题。对于初学者,您的Recurrance将永远是RecurranceDaily,因为您在构造函数中创建了Recurrance,在创建Recurrance之前无法设置RecurranceType。必须先创建对象,然后才能设置对象中的任何数据。除非您在构造函数本身中设置了该数据,否则您将始终具有默认状态(对于整数为0,再将其初始化为0)。

其次,您没有recurranceType的setter,并且由于该值是私有的,因此在构造之后无法设置它。

第三,你的Recurrance成员是一个只有一个getter的属性,但是在构造函数中你设置了它的值。这也不会编译,因为你没有设置。

答案 1 :(得分:0)

我不确定您是否向我们提供了足够的信息来提出有关设计方向的明智建议,但您可能需要考虑根据重复类型设置不同类型的任务,例如DailyTask, WeeklyTask,MonthlyTask。

然后,您可以将适当的逻辑放在Task子类中。例如。

var task = db.GetTaskById( 15 );
task.Schedule( startDate );

您的数据库代码将通过id获取任务,例如,确定它是WeeklyTask,并在其中设置适当的重复。然后它会有一个Schedule方法,对于从startDate开始的每周任务有意义。

public interface ITask
{
   public void Schedule( DateTime startDate );
}

public abstract class TaskBase : ITask
{
   // common methods...
   public abstract void Schedule( DateTime startDate );
}

public class WeeklyTask : TaskBase
{
   public override void Schedule( DateTime startDate )
   {
       var startWeek = GetStartOfWeek( startDate );
       var firstDate = startWeek.AddDays( DaysOfWeek[0] );
       ...
   }
}

答案 2 :(得分:0)

显然,你的场景中有更多的东西,而不是在这里看到的,但我会从SO About Inversion of Control And Dependency Injection看到这个答案。然后继续The Martin Fowler Article。使用IoC和DI,您可以将RecurrenceBase抽象为更像是带有“DoSomething”事件等的IRecur接口,以创建共性。也许是一个封装调度的“RecurrenceEventArgs”类。

我希望这会让你指出正确的方向。

答案 3 :(得分:0)

您正在创建一个继承层次结构 - 一个OO构造 - 但您显示的类肯定不是面向对象的,因为它们不包含任何行为并且只显示数据。

这是继承的不当使用,至少是导致你痛苦的部分原因。

当您继承时,您声明子类可以与父类使用相同的合约。对于您正在展示的课程以及您使用它们的方式,这根本不是真的。