• MOSS 2010:Visual Studio 2010开发体验(15)——LINQ to SharePoint


    这一篇我们来讨论的是,如何通过LINQ的技术实现对SharePoint 2010列表的读取。我还记得当年.NET Framework 3.5发布,第一次接触到Linq的时候那种不可思议的感觉。现在,SharePoint的开发也支持Linq啦,这真是一件值得欢欣鼓舞的事情。

    这篇文章的所有练习都基于下面这样列表。这个列表显示了员工的信息。作为演示目的,我只是添加了三个范例数据

    image

    目前针对MOSS 2010的开发,需要使用框架.NET Framework 3.5 而不是.NET Framework 4.0,而且编译的目标必须设置为Any CPU,或者X64。否则会出现一些莫名其妙的情况。这些是需要注意的,详细的介绍请参考我在下面这个博客文章

    http://www.cnblogs.com/chenxizhang/archive/2010/04/04/1704116.html

    在讲LINQ to SharePoint之前,我们稍微回顾一下之前是怎么访问SharePoint 列表的。我们会用到SharePoint所提供的组件对象模型(Object Model)去做,具体来说,我们大致有下面两种常见的做法

    【注意】如果你对SharePoint的对象模型不清楚,下面这篇文章可以帮助你理解 http://www.cnblogs.com/chenxizhang/archive/2010/04/05/1704550.html

    1. 通过读取SPList.Items

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.SharePoint;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var url = "http://localhost:45223/sites/dev";
                
                using (SPSite site = new SPSite(url))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        SPList list = web.Lists["Employees"];
                        foreach (SPListItem item in list.Items)
                        {
                            Console.WriteLine("FullName:{0},{1}  Age:{2}",
                                item["FirstName"],
                                item["LastName"],
                                item["Age"]);
                        }
    
                    }
                }
            }
        }
    }

    以上的代码是读取所有的员工的,假设我们要做筛选呢,例如我们只想看到那些年龄小于60岁的员工资料,我们会怎么做呢?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.SharePoint;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var url = "http://localhost:45223/sites/dev";
                
                using (SPSite site = new SPSite(url))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        SPList list = web.Lists["Employees"];
                        foreach (SPListItem item in list.Items)
                        {
                            if(int.Parse(item["Age"].ToString())<60)
                            Console.WriteLine("FullName:{0},{1}  Age:{2}",
                                item["FirstName"],
                                item["LastName"],
                                item["Age"]);
                        }
    
                    }
                }
            }
        }
    }
    

    没错,这可以实现我们的目的。其实如何结合LINQ to Object的技术,我们还可以像下面这样写代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.SharePoint;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var url = "http://localhost:45223/sites/dev";
                
                using (SPSite site = new SPSite(url))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        SPList list = web.Lists["Employees"];
    
    
                        var query = from SPListItem item in list.Items
                                    where int.Parse(item["Age"].ToString()) < 60
                                    select item;
    
                        foreach (SPListItem item in query)
                        {
                            
                            Console.WriteLine("FullName:{0},{1}  Age:{2}",
                                item["FirstName"],
                                item["LastName"],
                                item["Age"]);
                        }
    
                    }
                }
            }
        }
    }
    image 

    看起来不错,而且我们这里其实也用到了Linq的语法,不是吗?但大家要注意一下,上面三种写法,不管有没有进行筛选,也不管是否用到了LINQ语法,它们都有一个很大的问题,就是:他们都是把所有的SPListItem读取过来,然后再做处理的(例如做筛选),这意味着什么呢?

    假设列表的项目很多,例如有成千上万个员工记录,然而我们这个程序其实只要用到其中的一个员工,大家可以试想一下会是多大的一个资源浪费的操作。基于这样的理由,所以以前我们用得更多的可能是下面这种做法

    2. 通过CAML语法

    CAML是一个特殊的标记语言吧,它的全称是Collaborative Application Markup Language(协作应用程序标记语言)。这里有一个链接,如果有兴趣的朋友可以了解一下

    http://msdn.microsoft.com/zh-cn/library/ms426449.aspx

    这篇文章中,我们的重点当然不是介绍CAML,只是演示一下如何使用它来定义查询语法,对列表进行筛选。

    【注意】CAML的功能不仅仅限于列表查询,它甚至可以定义列表,和网站结构等等。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.SharePoint;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var url = "http://localhost:45223/sites/dev";
                
                using (SPSite site = new SPSite(url))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        SPList list = web.Lists["Employees"];
    
    
                        SPQuery query = new SPQuery();
                        query.Query = "<Where><Lt><FieldRef Name='Age' /><Value Type='Number'>60</Value></Lt></Where>";
                        foreach (SPListItem item in list.GetItems(query))
                        {
                            Console.WriteLine("FullName:{0},{1}  Age:{2}",
                                item["FirstName"],
                                item["LastName"],
                                item["Age"]);
                        }
    
                    }
    
    
                }
    
                Console.Read();
            }
        }
    }
    

    这个例子中,我们使用了一个全新的类型,SPQuery。它可以定义一串查询的语句。而SPList的GetItems方法就可以使用这个Query对象进行过滤。注意,这是在服务器端就过滤掉了数据,而不会把所有的SPListItem读取到我们的程序中来了。

    很显然的一个问题是,如果让你手工编写这个查询语句,恐怕是一件很困难的事情。所以以前我们一般都需要借助一些外部工具。其中最出名的一个工具就是U2U提供的CAML Query builder。

    关于如何使用U2U这个工具,以及有关注意事项,我之前也有一篇文章介绍

    http://www.cnblogs.com/chenxizhang/archive/2009/10/23/1588415.html

    CAML确实可以帮助我们实现灵活的查询,但无论如何,它的语法还是相对来说晦涩难懂的。所以,有一位叫bdesmet的开发人员实现了一套LINQ Provider,名称就是linqtoSharepoint,你可以通过下面的网站了解到有关信息

    http://linqtosharepoint.codeplex.com/

    【注意】这是一个开源项目,虽然名称很接近,但我们这篇博客文章并不是讨论它的使用。事实上,如果你还在使用MOSS 2007的话,它可能对你有些帮助。但我们现在如果使用MOSS 2010的话,就没有必要了。因为现在是内置了这个支持。

    【注意】我曾经在MOSS 2007的使用用过这个插件,但效果不尽如人意,尤其是如果你的网站中的列表是用中文命名的话。所以,如果你遇到了一些问题,也不必感到特别的诧异。

    3. 使用MOSS 2010全新的 LINQ 支持特性

    我们终于要切入正题了:如何使用MOSS 2010的LINQ特性来改善开发体验,以及它与之前的方法有何差别呢?

    为了使用LINQ的功能,我们第一步需要用一个工具生成一个代码文件,这个文件包含了所有列表的一个实体类。

    该工具叫SPMetal.exe,它的位置一般是在C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN目录中。

    image

    通过类似下面这样的方式执行该工具

    image

    该工具所生成的实体类文件大致如下

    image

    有了这个文件,接下来我们就可以将它添加到项目中,并且基于它编写代码来实现对列表的查询了。

    image 

    在该文件中,你发现有很多错误的提示。这是因为我们还没有添加一个程序集的引用。

    添加Microsoft.SharePoint.Linq.dll的引用,该程序集一般在c:\Program Files\Common Files\Microsoft Shared\web server extensions\14\ISAPI目录中

    image

    添加完引用之后,编译该项目,确保没有任何错误。

    接下来,我们看看代码应该如何修改

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.SharePoint;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var url = "http://localhost:45223/sites/dev";
    
                EntitiesDataContext ctx = new EntitiesDataContext(url);
                var query = from item in ctx.Employees
                            where item.Age < 60
                            select item;
    
    
                foreach (var item in query)
                {
    
                    Console.WriteLine("FullName:{0},{1} Age:{2}",
                        item.FirstName,
                        item.LastName,
                        item.Age);
                }
    
                Console.Read();
            }
        }
    }
    

    WOW, 我只能说,这样写代码的感觉是非常棒的:强类型、有智能感知支持、没有类型转换问题、更不需要记住那些晦涩难懂的CAML语句。。。。。。

    这就是LINQ的魅力吧,你也赶紧试试吧

  • 相关阅读:
    window.open 打开全屏窗口
    H5实现全屏与F11全屏
    泛型 总结
    java 反射
    静态工厂模式
    设计模式---单例模式
    String、List、array相互转换
    将数组转换成list
    将对象转换成json字符串的几种方式
    在map中放入数据时,如果key相同,会替换掉之前的相同key的数据
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1721573.html
Copyright © 2020-2023  润新知