我正在使用Web表单,C#,Asp.net。
众所周知,在此模型中,通常将UI和业务逻辑混在一起。如何有效地将它们分开?
我想使用的示例是:
我有一个GridView和一个DataTable(GridView绑定到DataTable,并且DataTable从存储过程中获取)。
我希望将GridView(UI)和DataTable(业务逻辑)分离。
为DataTable写包装器值得吗?是否有已被证明和测试的实用模式,您可以建议遵循?
如果有经验的人能有所启发,那就太好了。
而且,作为最后的说明,我想说ASP MVC现在不是一个选项,因此不建议这样做。
我的数据库访问层返回一个DataTable。
请注意,由于这是公司政策,因此我必须使用此数据库层。
最佳答案
我最近在通过UI层解耦相同内容的同时进行了此操作。
您可以看到我的进度here和here。
我认为A DataTable
不代表业务逻辑。具体来说,它是直接从数据库中提取数据。业务逻辑将数据变成真正有用的业务对象。
然后,第一步是将DataTable与Business对象分离。
您可以通过创建对象和组成数据表和数据表集合的List<object>
来做到这一点,然后可以创建一个显示这些对象的ListView。我在上面发布的链接中介绍了后面的步骤。前面的步骤很简单,如下所示:
创建一个代表您的对象的类。
遍历您的DataTable(或DataSet,或者无论如何检索数据),并将这些字段推入该对象(或该List<T>
)的属性中;
将该列表返回到Gridview或ListView进行显示。
这样,您的ListView或Gridview不会与您检索数据的方法紧密结合。如果您以后决定从JSON查询或XML文件中获取数据,该怎么办?然后,您必须将其构建到那里。
步骤1-从数据库获取数据
有多种方法可从数据库获取数据,在这里我无法遍历所有方法。我假设您已经知道如何从数据库检索数据,如果不知道,请遵循quite a few links。假设您已连接到数据库,并且正在使用SQLDataReader
检索数据。我们在那里接。
类图
Foo
----
id
Name
Description
这是方法:
private void FillDefault(SqlDataReader reader, Foos foo)
{
try
{
foo.id = Convert.ToInt32(reader[Foo.Properties.ID]);
foo.Name = reader[Foo.Properties.NAME].ToString();
if (!string.IsNullOrEmpty(
reader[Foo.Properties.DESCRIPTION].ToString()))
foo.Description =
reader[Foo.Properties.DESCRIPTION].ToString();
else foo.Description = string.Empty;
}
catch (Exception ex)
{
throw new Exception(
string.Format("Invalid Query.
Column '{0}' does not exist in SqlDataReader.",
ex.Message));
}
}
一旦发生这种情况,您可以通过针对
while
函数的SQLDataReader.Read()
循环中的该过程来返回列表。完成此操作后,让我们假设返回的
Foo
是一个列表。如果这样做,并按照我在上面给出的第一个链接,您可以将Dictionary<TKey, TValue>
替换为List<T>
并获得相同的结果(差异很小)。 Properties
类仅包含数据库中的列名,因此您可以在一个位置进行更改(以防万一)。数据表-基于注释的更新
您始终可以插入中间对象。在这种情况下,我将在DataTable和UI之间插入一个业务层,并且上面已经讨论了我要做什么。但是,数据表不是业务对象;它不是业务对象。它是数据库的直观表示。您不能将其传输到UI层并解耦。他们说您必须使用DataTable,是否说您必须将该DataTable传输到UI?我无法想象他们会。如果这样做,您将永远不会解耦。在DataTable和UI层之间始终需要一个中间对象。