• ADO.NET Data Service中更新和查询一对多实体集的注意事项


    尽管有人不喜欢ADO.NET Data Service,或者也有人不喜欢LINQ to SQL以及Entity Framework。但我还是愿意写这一篇文章,这是我在用的时候遇到的一个问题和解决方法。写出来,也可以为以后有类似问题的朋友提供一些帮助吧

    如果你不了解什么是ADO.NET Data Service,可以参考下面的一些链接和我之前的一些文章

    http://kb.cnblogs.com/page/43963/?page=1

    ADO.NET Data Service之CRUD操作

    如何在AJAX应用中访问ADO.NET Data Service

    如何在AJAX应用中访问ADO.NET Data Service(续)——基于jquery框架

    再谈谈ADO.NET Data Service

    ADO.NET Data Service中如何自定义Operation

    ADO.NET Data Service:如何做身份验证

    上面的一些文章从不同的角度介绍了ADO.NET Data Service,其实你也不必感到惊慌,要学习ADO.NET Data Service还是不太难的。

    好吧,言归正传吧,我今天要讲的一个问题是如何实现一对多实体集的更新

    1. 实体模型

    image

    从字面上就可以看出,这是一个订单和订单明细组成的一对多关系。一个订单可以拥有多个订单明细。

    2. 正常情况

    正常的Entity Framework中是如何实现插入一个订单并且附带插入多个订单明细呢?

                var ctx = new TestEntities();
                var order = new Orders() { OrderDate = DateTime.Now };//因为OrderID是自动递增的,所以无需提供
                order.OrderDetails.Add(new OrderDetails() { ItemID = 1 });
                order.OrderDetails.Add(new OrderDetails() { ItemID = 2 });
                //因为OrderDetails的OrderID是与Order关联的,所以也不需要提供
    
                ctx.AddToOrders(order);
                ctx.SaveChanges();

    3.在ADO.NET Data Service的客户端中如何做?

    上述的代码,如果拿到ADO.NET Data Service的客户端中来,稍作修改,就能够执行,而且不会报任何错误。但问题在于:

    它只是插入了订单资料,而会忽略订单明细资料

    这是为什么呢?简单的解释就是,因为ADO.NET Data Service是基于http的一个服务,考虑到数据量以及实际应用的情况,所以默认情况下,它是不会将一个对象所关联的其他对象都加载进来的,反过来讲也是一样,它不会自动将对象关联起来。也就是说,上面我们添加的两个OrderDetails的对象,其实没有跟Order进行关联,既然没有关联,自然就不会更新。

    那么应该怎么修改代码,才可以完成这个操作呢?

                var ctx = new localhost.TestEntities(new Uri("http://localhost:7949/WcfDataService.svc/"));
                var o = new localhost.Orders() { OrderDate = DateTime.Now };
                
                
                ctx.AddToOrders(o);
                ctx.AddRelatedObject(o, "OrderDetails", new localhost.OrderDetails() {ItemID = 2});
                ctx.AddRelatedObject(o, "OrderDetails", new localhost.OrderDetails() { ItemID = 3 });
                ctx.SaveChanges();

    注意,我们需要明确地AddRelatedObject.关于这一点,MSDN中也有明确的讲解。

    4.附录: 理解延迟加载

    本文附带讲一下所谓的延迟加载问题。刚才说到了,考虑数据量的问题,LINQ to SQL或者Entity Framework默认是不会自动加载一个对象所有的关联对象的。这有显而易见的好处,例如一个对象会有好多层的关联(例如:公司=》员工=》订单=》订单明细=》产品),如果全部加载进来非但耗时费力,也不是用户所需要的。

    延迟加载当然也有一个问题,就是它需要多次发起数据库查询。这是无法避免的,因为毕竟它需要加载过来。但这一点仍然是让人可以理解的,至少它是按需发起这些请求。

    我给大家看一个简单的代码

                var ctx = new TestEntities();
                var order = ctx.Orders.FirstOrDefault(o => o.OrderID == 15);
                MessageBox.Show(order.OrderDate.ToString());
                MessageBox.Show(order.OrderDetails.Count.ToString());

    这个查询很简单,它获取到一个订单对象,然后读取它的订购日期,然后还需要读取它的订单明细个数。那么,在延迟加载的情况下,需要几次数据库访问呢?答案是:两次。

    image

    值得注意的是,第二个查询是直到我们请求了order.OrderDetails.Count.ToString()才会运行的。

    那么,如果你在某些场合,确实想预先加载,不想延迟加载的话,你该怎么做呢?

                var ctx = new TestEntities();
                var order = ctx.Orders.FirstOrDefault(o => o.OrderID == 15);
                ctx.LoadProperty(order, "OrderDetails");
                MessageBox.Show(order.OrderDate.ToString());
                MessageBox.Show(order.OrderDetails.Count.ToString());

    大家注意看,我们可以添加一个LoadProperty的方法。就可以实现这样的功能。

    【注意】即便添加了这个方法,查询还是分成了两次,如下

    image

    这是Entity Framework与LINQ TO SQL不一样的。在LINQ TO SQL中(用LoadWith方法),如果是预先加载就只有一个查询语句了。(那个语句,可能很复杂)

    你可能会说,这个看起来没有什么优势啊,不是仍然需要两次查询码?这里的关键在于发起查询的时间。

    而尤其重要的一点是,如果你是使用ADO.NET Data Service编程,而不是直接使用Entity Framework。那么LoadProperty却是必须的,因为客户端根本就不会再发起第二次请求。

                var ctx = new localhost.TestEntities(new Uri("http://localhost:7949/WcfDataService.svc/"));
                var order = ctx.Orders.Where(o => o.OrderID == 15).FirstOrDefault();
                ctx.LoadProperty(order, "OrderDetails");
                MessageBox.Show(order.OrderDate.ToString());
                MessageBox.Show(order.OrderDetails.Count.ToString());

    【注意】上面的LoadProperty这行代码如果不加,虽然不会报告错误。但在最后那个MessageBox中,显示为0 ,而不是真正的2.(我目前测试的表里面有2行记录)

    5. 总结

    这一篇文章讲解了在ADO.NET Data Service中,加载和更新一对多实体集的相关概念、问题和解决方法。

  • 相关阅读:
    (转)130道ASP.NET面试题
    (转)c#对象内存模型
    (转)探讨:ASP.NET技术的学习顺序问题
    (转)ASP.NET缓存概念及其应用浅析
    Response.Redirect在新窗口打开网页
    转载 C# 序列化与反序列化意义详解
    简单进制转化
    简单成绩管理系统(没有存盘)
    kali不能ifconfig等简单命令
    蓝桥杯练习之开花(二分法查找)
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1751327.html
Copyright © 2020-2023  润新知