设为首页 收藏本站
查看: 570|回复: 0

[经验分享] 如何基于OM模型使用C#在程序中给SharePoint的BCS外部数据类型的字段赋值

[复制链接]

尚未签到

发表于 2015-9-24 09:35:12 | 显示全部楼层 |阅读模式
概述:
  外部内容类型和数据,SharePoint从2010这个版本开始就对BCS提供非常强大的支持,点点鼠标就可以取代以前直接编辑XML的方式来设置SharePoint到SQL数据库的连接。非常方便地在SharePoint中修改删除SQL数据库的数据,并且SharePoint还提供了字段级的支持,您可以在任何List当中插入一个External Data外部数据字段,用来引用SQL表中的某一行,并显示指定字段的值。 我们经常要用到程序去自动滴修改值,这个类型栏的值,是可以直接通过“Iiem[Field]=Value”这个语句简简单单地把它更改了的嘛?答案是否定的,如果要改这个BCS类型的值,您可能需要十几行代码,我们慢慢给您开讲。
  此时,您有没有觉得SharePoint就像一个万能插头一样,什么样的“数据”,都能插得进来呢? “公牛牌!” ,Oh no... 是 “母牛牌” ,你懂的!
  

准备工作
  在SharePoint 2010 和 SharePoint 2013 当中我们可以通过SharePoinit Desinger很方便地设置一个基于SQL SERVER的或是其它数据源的,“外部内容类型”,这样我们就可以在SharePoint 查询、修改、添加这个数据表,如下图所示:
  

  
  本教程不是初级入门教程,如果各位小学生不懂如何进行BCS的基本操作,那么我们的大神门在度娘上已经留下了大量的痕迹,尽情地去Search(色)吧。
  假设,现在我们已经有了如下的其于BCS的字段叫“name”,如下图,它是从一个叫“dept stuff” 这个外部类型当中读取数据的,我们还勾选了的相关的 “部门、移动号码”,作为显示字段。
  
  

重要概念
  要引用如下的3个DLL文件,
  
  我的using 是这样的:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Xml;
using Microsoft.SharePoint.BusinessData;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.BusinessData.SharedService;
using System.Data;
using Microsoft.BusinessData.Runtime;
using Microsoft.BusinessData.MetadataModel;
using Microsoft.BusinessData.MetadataModel.Collections;
using System.Web;
using Microsoft.SharePoint.BusinessData.Infrastructure;
using System.Globalization;

  

1. 存了什么:Identity
  其实就是数据库中作为“标识”和“主键”的那一列,在创建SharePoint的Entity(即实体)时,一定要把这个Identity选出来,这是后面进行编程的基础,如果不设定这个的话,只能“呵呵”你了,因为我也不知道会发生什么。
  如下图,大家可以偷窥到,我们2个优秀的员工,包XX和蒋XX,所在的部门和移动号码,千万别认为你们所见的,就是在LIST所实际存储的,在External Data类型的字段中,除了Identity什么也不实际存储,那她们的“名字、部门、电话”,这些值是什么呢?
  是缓存!Cache! (此处省略1000字原理),记住包括您建的这个叫name的栏,存储的也是Cache,所以当你天真的使用
  item["name"]="奥巴马"
  来赋值后,你会发现name:部门和name:移动号码,根本没有改变,不是因为我们没有员工叫 “奥巴马” ,而是Identity的问题,所以我们给这种类型字段赋新值,值并不重要,你必须要知道新值在数据库表中的Identity那列的值!
  
  

2. 在哪存的:SPField.RelatedField
  那你要问了,这个Identity,既然不存储在所建的那个External Field里,那存储在哪里呢,YES! 就是在这个RelatedField里,在微软网站上,关于这个属性的说明,是如此简单和无节操,所以我们取Identity数据的时候要使用这样的语句,同样赋值也是:



string entityId= listItem[dataField.RelatedField].ToString();

  
  

3. 怎么加密存的:EntityInstanceIdEncoder
  天哪,知道存了什么,存在哪里,读出来却是乱码一片,经过大神Dosboy的研究发现了,这个Identity,竟然是加密码保存的,用得就是这个加密的方法。这是要把人整死的节奏嘛?
  测试看看是不是加密:EntityInstanceIdEncoder.IsEncodedIdentifier
  用来解密:EntityInstanceIdEncoder.DecodeEntityInstanceId
  所以读取Identity的语句应该是这样子的:



1                SPBusinessDataField dataField = listItem.Fields["name"] as SPBusinessDataField;
2                         string entityId= listItem[dataField.RelatedField].ToString();
3                         Identity id =null;
4                         if (EntityInstanceIdEncoder.IsEncodedIdentifier(entityId))
5                         {
6                             object[] oIDList = EntityInstanceIdEncoder.DecodeEntityInstanceId(entityId);
7                             id = new Identity(oIDList[0]);
8
9
10                         }
11                         else
12                             id = new Identity(entityId);
  取出来的变量id,就是Identity类型的。如果要显示出来,就用这样的:
  Console.WriteLine(id.GetIdentifierValues()[0].ToString ());
  搞清楚外部数据External Data相关的存储的情况以后,我们就可以赋值的操作了

给External Data栏赋值的过程

1. 搞清楚你要赋的值在源数据库表中那个"主键"的栏的值是多少?

  有些人就说了,兄弟我只知道新值,比如本例叫“本.拉灯”,那怎么办,对不起,请在程序中编程查询ID的值,比如“本.拉灯”的员工号(一定很排前)。这是前提,否则不是违背了External Data的原本意义了嘛,就是通过让你选一行数据,然后显示数据库中的值。
  

2. 给 RelatedField 赋 Identity的值,并根据Identity的值找到External Entity中的新值的那行:



public static IEntityInstance GetEntityInstance(SPBusinessDataField dataField, string entityId, SPSite site, SPListItem item)
{

SPServiceContext context = SPServiceContext.GetContext(site);
IMetadataCatalog catalog = null;
BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>(String.Empty);
if (null != bdcService)
{
catalog = bdcService.GetDatabaseBackedMetadataCatalog(context);
}
IEntity entity = catalog.GetEntity(dataField.EntityNamespace, dataField.EntityName);
ILobSystem lobSystem = entity.GetLobSystem();
ILobSystemInstance LobSysteminstance = lobSystem.GetLobSystemInstances()[dataField.SystemInstanceName];
IEntityInstance entInstance = null;
// Get methods collection
foreach (KeyValuePair<string, IMethod> method in entity.GetMethods())
{
// Get current method’s instance
IMethodInstance methodInstance = method.Value.GetMethodInstances()[method.Key];
// Execute specific finder method.
if (methodInstance.MethodInstanceType == MethodInstanceType.SpecificFinder)
{   
Identity id = null;
if (EntityInstanceIdEncoder.IsEncodedIdentifier(entityId))
{
object[] oIDList = EntityInstanceIdEncoder.DecodeEntityInstanceId(entityId);
id = new Identity(oIDList[0]);
// Execute specific finder method and get the entity instance
entInstance = entity.FindSpecific(id, entity.GetLobSystem().GetLobSystemInstances()[0].Value);
item[dataField.RelatedField] = entityId.ToString();
}
else
{
object oID = GetTypedIDValue(entityId, entity);
id = new Identity(oID);
string encodedIdentifier = EntityInstanceIdEncoder.EncodeEntityInstanceId(new object[] { oID });
// Execute specific finder method and get the entity instance
// Console.WriteLine(entity.Name + ":" + entity.GetLobSystem().GetLobSystemInstances()[0].Value.Name);
entInstance = entity.FindSpecific(id, entity.GetLobSystem().GetLobSystemInstances()[0].Value);

item[dataField.RelatedField] = encodedIdentifier;
}
}
}
return entInstance;
}
public static object GetTypedIDValue(string sID, IEntity oEntity)
{
IIdentifierCollection type = oEntity.GetIdentifiers();
String sIdentifierType = type[0].IdentifierType.FullName.ToLower().Replace("system.", String.Empty);
object oID = null;
//find the instance value based on the given identifier type
switch (sIdentifierType)
{
case "string":
oID = sID;
break;
case "datetime":
oID = DateTime.Parse(sID, CultureInfo.CurrentCulture);
break;
case "boolean":
oID = Boolean.Parse(sID);
break;
case "int64":
oID = Int64.Parse(sID);
break;
case "int32":
oID = Int32.Parse(sID);
break;
case "int16":
oID = Int16.Parse(sID);
break;
case "double":
oID = Double.Parse(sID);
break;
case "char":
oID = Char.Parse(sID);
break;
case "guid":
oID = new Guid(sID);
break;
default:
oID = sID;
break;
}
return oID;
}
  
  以上的代码涉及很多关于BCS很多很多的概念,什么实例什么实体,我只想说,你就复制、粘贴吧,你唯一要搞清楚的就是2件事件:


  • 列表的Externl Data(就是外部类型)的栏的名字,还有你网站的URL是什么。
  • 新值,的Identity是什么。
  

3. 给其它显示的栏 赋 显示的值
  第2步做完后,就要给其它栏,本例是名字(对的也属于其它栏)、手机、部门,赋显示的值哦,用这个代码:



public static void SetSecondaryFields(SPListItem listItem, SPBusinessDataField dataField, IEntityInstance entityInstance)
{
// Convert the entity to a formatted datatable
DataTable dtBDCData = entityInstance.EntityAsFormattedDataTable;
// Set the BCS field itself (Display Value)
listItem[dataField.Id] = dtBDCData.Rows[0][dataField.BdcFieldName].ToString();
// Get the specific finder method to get the columns that returns
IMethodInstance method = entityInstance.Entity.GetMethodInstances(MethodInstanceType.SpecificFinder)[0].Value;
ITypeDescriptorCollection oDescriptors = method.GetReturnTypeDescriptor().GetChildTypeDescriptors()[0].GetChildTypeDescriptors();
// Set the column names to the correct values
foreach (ITypeDescriptor oType in oDescriptors)
{
if (oType.ContainsLocalizedDisplayName())
{
if (dtBDCData.Columns.Contains(oType.Name))
{
dtBDCData.Columns[oType.Name].ColumnName = oType.GetLocalizedDisplayName();
}
}
}
// get the secondary field display names; these should be set
string[] sSecondaryFieldsDisplayNames = dataField.GetSecondaryFieldsNames();
// loop through the fields and set each column to its value
foreach (string columnNameint in sSecondaryFieldsDisplayNames)
{
Guid gFieldID = listItem.Fields[String.Format("{0}: {1}", dataField.Title, columnNameint)].Id;
listItem[gFieldID] = dtBDCData.Rows[0][columnNameint].ToString();
}
listItem.Update();
}
}
  
  以上还是涉及涉及很多概念,不用管,直接,复制、粘贴这个函数就行。
  

4. 示例如何在命令行程序中使用如上的代码:
    把上面3个函数,把在一个静态的类中,我们叫myF,然后在Main函数中,写上如下的代码,这个代码是做这样的事情的.
  这个网站集的URL是: http://r720/sites/demo
  列表的名称是:External Field

  外部数据列叫:name (附带显示:部门、移动号码2列)
  我现在要把所有的行,的name栏都换成比刚才2位优秀员工更优秀的员工:本拉灯(他的代号200),代码如下,这个你不能复制粘贴,要换成自己的网站的情况:)



using (SPSite spSite = new SPSite("http://r720/sites/demo"))
{
using (SPWeb spWeb = spSite.RootWeb)
{
SPList list = spWeb.Lists["External Field"];
foreach (SPListItem  listItem  in list.Items)
{

SPBusinessDataField dataField = listItem.Fields["name"] as SPBusinessDataField;
IEntityInstance entityinst = myF.GetEntityInstance(dataField, "200",new SPSite("http://r720/sites/demo"), listItem);
myF.SetSecondaryFields(listItem, dataField, entityinst);

}
}
}
Console.ReadLine();
  
  故事的核心就这么2个语句:



IEntityInstance entityinst = GetEntityInstance(【外部字段】, 【新值ID】,【网站集】,【当前列表项】);
SetSecondaryFields(【当前列表项】,【外部字段】,entityinst);
  
  我们再看看效果吧,(千万别打电话哦,有美国人监听呢:))
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-118046-1-1.html 上篇帖子: 在SharePoint解决方案中使用JavaScript (1) – 引用.js文件 下篇帖子: 如何基于OM模型使用C#在程序中给SharePoint的BCS外部数据类型的字段赋值
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表