【问题标题】:Returning data from database in .net: Return a DataTable or LIst<T>?从 .net 中的数据库返回数据:返回 DataTable 或 LIst<T>?
【发布时间】:2010-12-13 01:13:02
【问题描述】:

我正在努力将良好的数据库设计概念与良好的面向对象设计联系起来。

传统上,如果我想在转发器中显示新闻报道列表,我会使用类似:

<script runat="server">

    void ShowNews()
    {
        rptNewsStories.DataSource = News.GetAllNews(); // Returns a DataTable
        rptNewsStories.DataBind();
    }

</script>

<asp:Repeater id="rptNewsStories" runat="server">
    <ItemTemplate>
        <div>
            <span class="Title"><%# Eval("Title")"%> (<%# Eval("Location")"%>)</span>
            <p>
                <%# Eval("Summary")"%>
            </p>
            <ul>
                <li>Added by: <%# Eval("AddedByFullName")%></li>
                <li>Added on: <%# Eval("AddedOn")%></li>
            </ul>
        </div>
    </ItemTemplate>
</asp:Repeater>

这里 News.GetAllNews() 返回一个 DataTable,它只是存储过程返回的内容的转储。存储过程被编写为使用连接返回数据,因此它的数据价值不止一张表。

这样做的好处在于,在数据库中存储过程可以从 News 表中存在的 AddedByID 中查找谁添加了新闻故事并返回人员作为返回的 AddedByFullName 值的全名。

但是,如果我尝试放弃使用 DataTable 并返回 News 对象列表,我会得到以下信息:

<script runat="server">

    void ShowNews()
    {
        rptNewsStories.DataSource = News.GetAllNews(); // Returns a List<News>
        rptNewsStories.DataBind();
    }

</script>

<asp:Repeater id="rptNewsStories" runat="server">
    <ItemTemplate>
        <div>
            <span class="Title"><%# Eval("Title")"%> (<%# Eval("Location")"%>)</span>
            <p>
                <%# Eval("Summary")"%>
            </p>
            <ul>
                <li>Added by: <!-- Here there is only a AddedByUserID, not an AddedByFullName value --></li>
                <li>Added on: <%# Eval("AddedOn")%></li>
            </ul>
        </div>
    </ItemTemplate>
</asp:Repeater>

但现在我遇到的问题是我想要显示的某些值(例如 AddedByFullName)在 News 对象中不存在,因为它们不是明确设置的,但不是从对象中的查找 ID 中检索。

我想返回对象而不是 DataTables,但我不知道弥合这一差距的最佳方法。

我:
* 在 News 类中为每个可以从数据库返回的与此数据相关的附加值创建附加属性?
* 对于有很多附加值的特定情况,请坚持使用 DataTables

还是我完全走错了路!

【问题讨论】:

    标签: c# sql-server generics oop datatable


    【解决方案1】:

    好问题:

    您可以采取以下几种方法:

    1. 您可以检索转发器绑定事件所需的附加数据,并将其填充到返回的每条新闻记录的“占位符”中。由于额外的查询,这存在性能问题,但它会起作用。

    2. 如果可能的话,我会修改新闻对象以包含附加信息,或者创建一个继承自包含附加信息或属性的新闻对象的对象。

    希望这会有所帮助 :-) +1

    编辑/评论: 我认为你在设计中看到的摩擦是你没有承认你的新闻对象和我称之为作者/贡献者之间的“有”关系。您在查询中进行的连接只是在掩饰对象模型中缺少关系。

    【讨论】:

    • 感谢您的输入 Achilles:1) 类似于 Gregoire 的建议。就像你说它会完成这项工作,但这种方法似乎只是额外的工作? 2)我知道这会更有效率,但它仍然感觉有点刺眼......虽然我更喜欢它而不是选项 1 我的目的是我希望得到一个感觉正确的建议,因为这些方法感觉不太像完美契合。
    • 我认为你在设计中看到的摩擦是你没有承认你的新闻对象和我称之为作者/贡献者之间的“有”关系。您在查询中所做的连接只是掩饰对象模型中缺少关系。
    【解决方案2】:

    你可以试试这个,也许不是更好的解决方案:

    void ShowNews()
    {   
        User[] usersConcerned = News.GetAllUsersLinkedWithNews(); //only return the users concerned by the news
        List<News> news = News.GetAllNews();
        foreach(News item in news)
        {
           item.AddedByUser = usersConcerned.FirstOrDefault(u=>u.Id == item.AddedByUserID);
        }
        rptNewsStories.DataSource = news ; 
        rptNewsStories.DataBind();
    }
    

    【讨论】:

    • 我确实想到了这种方法,但它似乎正在做一些可以通过存储过程中的连接更好地处理的事情。但是,也许这更像是面向对象的? :)
    • @Peter,您应该在数据库级别进行数据过滤。您可以传入 New.GetAllNews(usersConcerned) 并在您的 proc 中处理该数组。这可以根据您的数据显着减少网络流量。
    【解决方案3】:

    您的选择受限于您愿意用作数据访问的底层技术。目前,VS 工具集和 .Net 框架支持多种替代方案:

    除了 ADO.Net 类型的数据集之外,所有类型的数据集都允许您按照您的要求指定导航关系,无论是急切加载还是延迟加载。在您描述的情况下,使用这些技术的自然做法是在设计器中显式地对新闻文章和作者之间的关系进行建模,并让框架处理将适当数据加载到适当类型中的问题,最终意味着连接问题由应用程序数据访问层(框架)隐式处理,而不是由显式创建的存储过程。

    技术的选择会在您的代码中无处不在,从您如何获取数据到如何显示数据以及如何更新,这些技术都不能轻松互换。就个人而言,我发现使用 LINQ to SQL 可以在功能和复杂性之间取得适当的平衡。

    【讨论】:

    • 感谢您的输入 Remus - 我听说 MS 正在停止开发 LINQ to SQL 以支持实体框架。这是真的吗?如果是的话,您会鼓励使用这项技术进行新的开发吗?
    • @Peter:我不再和 MS 在一起了,所以我知道的不仅仅是公众知识。确实,EF 是未来的推荐方式,但鉴于 LINQ to SQL 与 EF 相比压倒性地采用,我会惊讶地看到它完全被放弃。
    • 我目前正在为一个 .net 3.5 项目使用并享受 LINQ2SQL。我的下一个大项目将使用 .net 4.0,所以我将使用 Entity Framework 4.0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多