SharePoint Designer 2010中的外部内容类型-WCF

本文将带领大家使用SharePoint Designer创建基于WCF服务的外部内容类型。

步骤

1、检查你的WCF服务已经宿主并可用。本文将使用封装AdventureWorks2000数据库的Contact表得到的WCF服务。 首先打开你的IIS管理器,导航到宿主你的WCF服务的网站,确保其正常运行。

SharePoint Designer 2010中的外部内容类型-WCF_第1张图片 

 

2、打开IE浏览器并导航到该服务的.svc文件。 你应该能够看到类型如下的页面,表示该WCF服务正在工作。

SharePoint Designer 2010中的外部内容类型-WCF_第2张图片 


WCF的检查工作结束。现在我们开始基于该WCF在SPD中创建我们的外部内容类型。

3、打开SharePoint Designer 2010并点击“打开网站”大按钮。

SharePoint Designer 2010中的外部内容类型-WCF_第3张图片
[点击图片可查看完整尺寸]

4、输入你的SharePoint站点URL地址并回车。SPD将会连接到该站点并获取信息。

SharePoint Designer 2010中的外部内容类型-WCF_第4张图片
[点击图片可查看完整尺寸]

5、从左侧导航窗格中点击外部内容类型。可以看到顶部的功能区也进行了相应的改变,反映当前的工作状态。

6、在功能区中,点击新建中的外部内容类型。

SharePoint Designer 2010中的外部内容类型-WCF_第5张图片

7、打开的摘要页面中,可以编辑和管理外部内容类型。

SharePoint Designer 2010中的外部内容类型-WCF_第6张图片
[点击图片可查看完整尺寸]

这里有一些类似超链接的标签,点击可设置值 。最上面的两个是名称和显示名称,设置其值为:

 

名称:联系人

显示名称:联系人 

 

接下来,我们选择一个外部数据源来进行连接。点击链接“点击此处发现数据源并定义操作”。

8、进入操作设计器视图。点击添加连接按钮。

SharePoint Designer 2010中的外部内容类型-WCF_第7张图片
[点击图片可查看完整尺寸]

9、选择数据源类型为 “WCF服务”

 

10、WCF连接窗口打开。这里我们需要填写有关我们WCF服务的一些连接信息,以便SharePoint Designer进行连接。根据上面我们检查到的WCF宿主情况,这里我填入:

服务元数据URL:http://contact/service.svc?WSDL

服务终结点URL:http://contact/service.svc 

SharePoint Designer 2010中的外部内容类型-WCF_第8张图片 

11、配置好WCF连接后,点击确定。这时将尝试连接到你的WCF服务。如果一切正常,你会看到所有可用的Web方法。

SharePoint Designer 2010中的外部内容类型-WCF_第9张图片 

12、我们需要创建相应的BCS操作。本例中,我们将使用GetContactFinder作为“读取列表”操作,使用GetContactSpecificFinder作为“读取项”操作。

13、右击 GetContactFinder并选择“新建读取列表”操作。

SharePoint Designer 2010中的外部内容类型-WCF_第10张图片 

14、在弹出的向导中,“返回参数” 一节中会提示一个错误信息,“应至少指定一个标识符”。选择ContactID并勾选“映射到标识符”。在标识符下拉框中选中ContactID。点击完成,创建好了读取列表操作。

SharePoint Designer 2010中的外部内容类型-WCF_第11张图片

 

15、右击GetContactSpecificFinder并选择新建“读取项”操作。

SharePoint Designer 2010中的外部内容类型-WCF_第12张图片 

16、在操作属性窗口中,输入参数一节我们需要映射该输入参数到标识符。选中contactid并在右侧的面板中勾上“映射到标识符”,并在标识符下拉框中选中ContactID。点击下一步。

SharePoint Designer 2010中的外部内容类型-WCF_第13张图片 

 

17、在返回参数一节,也包含一条错误提示指出需要映射标识符。为了修复该错误,在左侧选择ContactID,右侧勾选“映射到标识符” 并在标识符下拉框中选中ContactID。点击完成按钮。 

SharePoint Designer 2010中的外部内容类型-WCF_第14张图片

 

18、现在,右侧的ECT操作中已经有两个操作了。你也可以根据需要添加其他操作,如创建,更新等等。

SharePoint Designer 2010中的外部内容类型-WCF_第15张图片

 

19、按“Ctrl+S”键保存该ECT。 

 

20、我们可以打开SharePoint站点,创建外部列表绑到我们的外部内容类型。 

SharePoint Designer 2010中的外部内容类型-WCF_第16张图片

 

21、它会调用“读取列表”操作 (WCF中的Finder方法)来获取数据。

SharePoint Designer 2010中的外部内容类型-WCF_第17张图片


22、选中任意一条数据,然后点击“项目”功能区,其中的“查看项目”操作会调用WCF的Specific Finder方法,在弹出框中显示选中的项。 

SharePoint Designer 2010中的外部内容类型-WCF_第18张图片

 

SharePoint Designer 2010中的外部内容类型-WCF_第19张图片

 

附上本例中涉及的WCF相关代码,以备参考。

1、IAdventureWorks2000WCFService.cs

代码
using  System;
using  System.Collections.Generic;
using  System.Runtime.Serialization;
using  System.ServiceModel;

[ServiceContract]
public   interface  IAdventureWorks2000WCFService
{
  
      [OperationContract]
      List
< Contact >  GetContactFinder();
    
      [OperationContract]
      Contact GetContactSpecificFinder(Int32 contactid);
    
      [OperationContract]
      List
< Int32 >  GetContactIdEnumerator();
    
}

[DataContract]
public   class  Contact
{
  
      [DataMember]
      
public  Int32 ContactID
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String Salutation
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String FirstName
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String MiddleName
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String LastName
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  Boolean NameStyle
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String Phone
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String Suffix
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String EmailAddress
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String Password
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  Int32 EmailPromotion
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  DateTime ModifiedDate
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  Guid rowguid
      {
      
get ;
      
set ;
      }

    
      [DataMember]
      
public  String AdditionalContactInfo
      {
      
get ;
      
set ;
      }

    
}

 

2、 AdventureWorks2000WCFService.cs

代码
using  System;
using  System.Collections.Generic;
using  System.Data;
using  System.Data.SqlClient;
public   class  AdventureWorks2000WCFService : IAdventureWorks2000WCFService
{
  
private   const   string  connectionString  =   @" Persist Security Info=False;User ID=xxx;Password=xxx;Server=localhost;Connect Timeout=30;Initial Catalog=AdventureWorks2000 " ;
  


  
  AdventureWorks2000WCFService()
  {    
  }

  
  
public  List < Contact >  GetContactFinder()
  {
  List
< Contact >  contactList  =   new  List < Contact > ();

  
const   string  sqlQuery  =   @" Select * From dbo.[Contact]  " ;

  
using  (SqlConnection sqlConnection  =   new  SqlConnection(connectionString))
  {
  sqlConnection.Open();

  SqlCommand comm 
=   new  SqlCommand(sqlQuery, sqlConnection);
  
  DataSet dataSet 
=   new  DataSet();

  SqlDataAdapter adapter 
=   new  SqlDataAdapter(comm);
  adapter.Fill(dataSet, 
@" dbo.[Contact] " );

  
foreach  (DataRow dr  in  dataSet.Tables[ 0 ].Rows)
  {
  Contact contact 
=   new  Contact();

  contact.ContactID 
=  dr[ " ContactID " is  DBNull  ?   0  : (Int32)dr[ " ContactID " ];
contact.Salutation 
=  dr[ " Salutation " is  DBNull  ?   string .Empty : (String)dr[ " Salutation " ];
contact.FirstName 
=  dr[ " FirstName " is  DBNull  ?   string .Empty : (String)dr[ " FirstName " ];
contact.MiddleName 
=  dr[ " MiddleName " is  DBNull  ?   string .Empty : (String)dr[ " MiddleName " ];
contact.LastName 
=  dr[ " LastName " is  DBNull  ?   string .Empty : (String)dr[ " LastName " ];
contact.NameStyle 
=  dr[ " NameStyle " is  DBNull  ?   false  : (Boolean)dr[ " NameStyle " ];
contact.Phone 
=  dr[ " Phone " is  DBNull  ?   string .Empty : (String)dr[ " Phone " ];
contact.Suffix 
=  dr[ " Suffix " is  DBNull  ?   string .Empty : (String)dr[ " Suffix " ];
contact.EmailAddress 
=  dr[ " EmailAddress " is  DBNull  ?   string .Empty : (String)dr[ " EmailAddress " ];
contact.Password 
=  dr[ " Password " is  DBNull  ?   string .Empty : (String)dr[ " Password " ];
contact.EmailPromotion 
=  dr[ " EmailPromotion " is  DBNull  ?   0  : (Int32)dr[ " EmailPromotion " ];
contact.ModifiedDate 
=  dr[ " ModifiedDate " is  DBNull  ?  DateTime.MinValue : (DateTime)dr[ " ModifiedDate " ];
contact.rowguid 
=  dr[ " rowguid " is  DBNull  ?  Guid.Empty : (Guid)dr[ " rowguid " ];
contact.AdditionalContactInfo 
=  dr[ " AdditionalContactInfo " is  DBNull  ?   string .Empty : (String)dr[ " AdditionalContactInfo " ];


  contactList.Add(contact);
  }
  }


  
return  contactList;
  }
public  Contact GetContactSpecificFinder(Int32 contactid)
  {
  Contact contact 
=   new  Contact();

  
const   string  sqlQuery  =   @" Select * From dbo.[Contact] Where (ContactID=@ContactID) " ;

  
using  (SqlConnection sqlConnection  =   new  SqlConnection(connectionString))
  {
  sqlConnection.Open();

  SqlCommand comm 
=   new  SqlCommand(sqlQuery, sqlConnection);
  comm.Parameters.AddWithValue(
" @ContactID " , contactid);
  DataSet dataSet 
=   new  DataSet();

  SqlDataAdapter adapter 
=   new  SqlDataAdapter(comm);
  adapter.Fill(dataSet, 
@" dbo.[Contact] " );

  
if (dataSet.Tables[ 0 ].Rows.Count  >   0 )
  {
  DataRow dr 
=  dataSet.Tables[ 0 ].Rows[ 0 ];
  contact.ContactID 
=  dr[ " ContactID " is  DBNull  ?   0  : (Int32)dr[ " ContactID " ];
contact.Salutation 
=  dr[ " Salutation " is  DBNull  ?   string .Empty : (String)dr[ " Salutation " ];
contact.FirstName 
=  dr[ " FirstName " is  DBNull  ?   string .Empty : (String)dr[ " FirstName " ];
contact.MiddleName 
=  dr[ " MiddleName " is  DBNull  ?   string .Empty : (String)dr[ " MiddleName " ];
contact.LastName 
=  dr[ " LastName " is  DBNull  ?   string .Empty : (String)dr[ " LastName " ];
contact.NameStyle 
=  dr[ " NameStyle " is  DBNull  ?   false  : (Boolean)dr[ " NameStyle " ];
contact.Phone 
=  dr[ " Phone " is  DBNull  ?   string .Empty : (String)dr[ " Phone " ];
contact.Suffix 
=  dr[ " Suffix " is  DBNull  ?   string .Empty : (String)dr[ " Suffix " ];
contact.EmailAddress 
=  dr[ " EmailAddress " is  DBNull  ?   string .Empty : (String)dr[ " EmailAddress " ];
contact.Password 
=  dr[ " Password " is  DBNull  ?   string .Empty : (String)dr[ " Password " ];
contact.EmailPromotion 
=  dr[ " EmailPromotion " is  DBNull  ?   0  : (Int32)dr[ " EmailPromotion " ];
contact.ModifiedDate 
=  dr[ " ModifiedDate " is  DBNull  ?  DateTime.MinValue : (DateTime)dr[ " ModifiedDate " ];
contact.rowguid 
=  dr[ " rowguid " is  DBNull  ?  Guid.Empty : (Guid)dr[ " rowguid " ];
contact.AdditionalContactInfo 
=  dr[ " AdditionalContactInfo " is  DBNull  ?   string .Empty : (String)dr[ " AdditionalContactInfo " ];

  }
  }


  
return  contact;
  }
public  List < Int32 >  GetContactIdEnumerator()
  {
  List
< Int32 >  ids  =   new  List < Int32 > ();

  
const   string  sqlQuery  =   @" Select ContactID from dbo.[Contact] " ;

  
using  (SqlConnection sqlConnection  =   new  SqlConnection(connectionString))
  {
  sqlConnection.Open();

  SqlCommand comm 
=   new  SqlCommand(sqlQuery, sqlConnection);

  DataSet dataSet 
=   new  DataSet();

  SqlDataAdapter adapter 
=   new  SqlDataAdapter(comm);
  adapter.Fill(dataSet, 
@" dbo.[Contact] " );

  
foreach  (DataRow dr  in  dataSet.Tables[ 0 ].Rows)
  {
  ids.Add(dr[
" ContactID " is  DBNull  ?   0  : (Int32)dr[ " ContactID " ]);
  }
  }


  
return  ids;
  }


}

 

3、Service.svc

<% @ ServiceHost Language = " C# "  Debug = " true "  Service = " AdventureWorks2000WCFService "  CodeBehind = " ~/App_Code/AdventureWorks2000WCFService.cs "   %>

 

4、Web.config

代码
<? xml version="1.0" ?>
<!--
    Note: As an alternative to hand editing this file you can use the 
    web admin tool to configure settings for your application. Use
    the Website->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in 
    machine.config.comments usually located in 
    \Windows\Microsoft.Net\Framework\v2.x\Config 
-->
< configuration >
    
< configSections >
        
< sectionGroup  name ="system.web.extensions"  type ="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
            
< sectionGroup  name ="scripting"  type ="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
                
< section  name ="scriptResourceHandler"  type ="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="MachineToApplication" />
                
< sectionGroup  name ="webServices"  type ="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
                    
< section  name ="jsonSerialization"  type ="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="Everywhere" />
                    
< section  name ="profileService"  type ="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="MachineToApplication" />
                    
< section  name ="authenticationService"  type ="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="MachineToApplication" />
                    
< section  name ="roleService"  type ="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="MachineToApplication" />
                
</ sectionGroup >
            
</ sectionGroup >
        
</ sectionGroup >
    
</ configSections >
    
< appSettings />
    
< connectionStrings />
    
< system.web >
        
<!--
            Set compilation debug="true" to insert debugging 
            symbols into the compiled page. Because this 
            affects performance, set this value to true only 
            during development.
        
-->
        
< compilation  debug ="true" >
            
< assemblies >
                
< add  assembly ="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
                
< add  assembly ="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
                
< add  assembly ="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
                
< add  assembly ="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
        
      
</ assemblies >
        
</ compilation >
        
<!--
            The <authentication> section enables configuration 
            of the security authentication mode used by 
            ASP.NET to identify an incoming user. 
        
-->
        
< authentication  mode ="Windows" />
        
<!--
            The <customErrors> section enables configuration 
            of what to do if/when an unhandled error occurs 
            during the execution of a request. Specifically, 
            it enables developers to configure html error pages 
            to be displayed in place of a error stack trace.

        <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
            <error statusCode="403" redirect="NoAccess.htm" />
            <error statusCode="404" redirect="FileNotFound.htm" />
        </customErrors>
        
-->
        
< pages >
            
< controls >
                
< add  tagPrefix ="asp"  namespace ="System.Web.UI"  assembly ="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
            
</ controls >
        
</ pages >
        
< httpHandlers >
            
< remove  verb ="*"  path ="*.asmx" />
            
< add  verb ="*"  path ="*.asmx"  validate ="false"  type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
            
< add  verb ="*"  path ="*_AppService.axd"  validate ="false"  type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
            
< add  verb ="GET,HEAD"  path ="ScriptResource.axd"  type ="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  validate ="false" />
        
</ httpHandlers >
        
< httpModules >
            
< add  name ="ScriptModule"  type ="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        
</ httpModules >
    
</ system.web >
    
< system.codedom >
        
< compilers >
            
< compiler  language ="c#;cs;csharp"  extension =".cs"  warningLevel ="4"  type ="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
                
< providerOption  name ="CompilerVersion"  value ="v3.5" />
                
< providerOption  name ="WarnAsError"  value ="false" />
            
</ compiler >
            
< compiler  language ="vb;vbs;visualbasic;vbscript"  extension =".vb"  warningLevel ="4"  type ="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
                
< providerOption  name ="CompilerVersion"  value ="v3.5" />
                
< providerOption  name ="OptionInfer"  value ="true" />
                
< providerOption  name ="WarnAsError"  value ="false" />
            
</ compiler >
        
</ compilers >
    
</ system.codedom >
    
< system.web.extensions >
        
< scripting >
            
< webServices >
                
<!--
              Uncomment this section to enable the authentication service. Include 
              requireSSL="true" if appropriate. 

          <authenticationService enabled="true" requireSSL = "true|false"/>
          
-->
                
<!--
              Uncomment these lines to enable the profile service, and to choose the 
              profile properties that can be retrieved and modified in ASP.NET AJAX 
              applications.

           <profileService enabled="true"
                           readAccessProperties="propertyname1,propertyname2"
                           writeAccessProperties="propertyname1,propertyname2" />
          
-->
                
<!--
              Uncomment this section to enable the role service.

          <roleService enabled="true"/>
          
-->
            
</ webServices >
            
<!--
        <scriptResourceHandler enableCompression="true" enableCaching="true" />
        
-->
        
</ scripting >
    
</ system.web.extensions >
    
<!--
        The system.webServer section is required for running ASP.NET AJAX under Internet
        Information Services 7.0.  It is not necessary for previous version of IIS.
    
-->
    
< system.webServer >
        
< validation  validateIntegratedModeConfiguration ="false" />
        
< modules >
            
< add  name ="ScriptModule"  preCondition ="integratedMode"  type ="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        
</ modules >
        
< handlers >
            
< remove  name ="WebServiceHandlerFactory-Integrated" />
            
< add  name ="ScriptHandlerFactory"  verb ="*"  path ="*.asmx"  preCondition ="integratedMode"  type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
            
< add  name ="ScriptHandlerFactoryAppServices"  verb ="*"  path ="*_AppService.axd"  preCondition ="integratedMode"  type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
            
< add  name ="ScriptResource"  preCondition ="integratedMode"  verb ="GET,HEAD"  path ="ScriptResource.axd"  type ="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        
</ handlers >
    
< directoryBrowse  enabled ="true"   />
    
</ system.webServer >
    
< system.serviceModel >
        
< services >
            
< service  name ="AdventureWorks2000WCFService"  behaviorConfiguration ="ServiceBehavior" >
                
<!--  Service Endpoints  -->
                
< endpoint  address =""  binding ="basicHttpBinding"  contract ="IAdventureWorks2000WCFService" >
                    
<!--  
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          
-->
                    
< identity >
                        
< dns  value ="contact" />
                    
</ identity >
                
</ endpoint >
                
< endpoint  address ="mex"  binding ="mexHttpBinding"  contract ="IMetadataExchange" />
            
</ service >
        
</ services >

    
< behaviors >
            
< serviceBehaviors >
                
< behavior  name ="ServiceBehavior" >
          
< dataContractSerializer  maxItemsInObjectGraph ="2147483647" />
                    
<!--  To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment  -->
                    
< serviceMetadata  httpGetEnabled ="true" />
                    
<!--  To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information  -->
                    
< serviceDebug  includeExceptionDetailInFaults ="false" />
                
</ behavior >
            
</ serviceBehaviors >
        
</ behaviors >
    
</ system.serviceModel >
</ configuration >

 

 

参考资料

spd external content type from wcf

Large List Throttling for External Lists in SharePoint 2010

BCS PowerShell: Introduction and Throttle Management

你可能感兴趣的:(SharePoint)