Как загрузить данные BDC из URL BDC?
-
26-09-2019 - |
Вопрос
Я делаю это в SharePoint 2010, но не будет удивлен, если проблема существует в SharePoint 2007 и имеет то же решение.
У меня есть триммер безопасности выполнения в моих данных BDC. Я ожидал, что триммер безопасности предоставляет мне URL-адреса, основанные на URL-адреса профиля «по умолчанию», определенного в модели. К сожалению, это не так. Это дает мне URL, как: BDC3: // amms_amms / default / 00000000% 252d0000000000000000000000000000000000000000 / 1971 / AMM0000000000 / 1971 / AMMS / 1973? S_ID = IBQAAAAAAAAAA = & S_CE = 07NK0004080G10003O03VVF
Мне нужно получить свойства этого объекта (действительно просто основное значение ключей). Любая идея, как я делаю это с объектной моделью BDC? Следующая ссылка, похоже, обеспечивает некоторую помощь, но я не видел ничего, что потребляет URL выше.
http://msdn.microsoft.com/en-us/library/ee556400.aspx.
Обновление: я вижу, что SharePoint 2007 имеет AccessChecker (http://msdn.microsoft.com/en-us/library/aa981124.aspx) и 2010, скорее всего, имеет это (не могу найти хорошую документацию на 2010 год) Отказ Мы не можем легко иметь дескрипторы безопасности в базе данных, но метод AccessChecker может быть достаточно.
Выкапывая немного дальше Я вижу, что Microsoft.Office.server.search.connector.bdc.bdcsecuritytrimmermer - это то, что, вероятно, используется AccessChecker в SharePoint 2010. Похоже, что это делает запрос к БД на URL. Кажется, неэффективно, даже если он делает это на нескольких потоках (которые заявляют о документации за 2007 год). Я думаю, что я бы предпочел допустить информацию в один звонок на один веб-сервис, но нахожусь на заборе ...
Решение
Хорошо, вот упрощение моего предыдущего ответа. Похоже, что вы можете полностью избежать отражения:
using Microsoft.BusinessData.Runtime;
using Microsoft.Office.Server.Search.Connector;
using Microsoft.Office.Server.Search.Query;
private string[] GetIds(IList<string> documentCrawlUrls)
{
string[] ids = new String[documentCrawlUrls.Count];
for (int i = 0; i < documentCrawlUrls.Count; i++)
{
try
{
string url = documentCrawlUrls[i];
string id = new Microsoft.Office.Server.Search.Connector.UriParser(new Uri(url)).QueryStringParameters["s_id"];
ids[i] = Identity.Deserialize(id).GetIdentifierValues()[0].ToString();
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine("Error: " + ex.Message);
}
}
return ids;
}
Обратите внимание, что я пытался избежать использования Uriparser от Microsoft.Office.server.search.connector с использованием типа Code:
string id = HttpUtility.ParseQueryString(new Uri(url).Query)["s_id"];
ids[i] = Identity.Deserialize(id.ToUpper()).GetIdentifierValues()[0].ToString();
К сожалению, это работало для некоторых идентификаторов, а не других. Я решил не расследовать дальше и просто использовать специальный урипарес. В одном примере IDS I искал, были «5,20,21,7,8,6,14,19,17,18,8,8,6,14,19,17,18,4», но этот второй подход дал мне «5,20 21 24581,8, 24580 24588 24593,17,24592,4 ". Это наступило на несколько минут, так как первые 3 были правильными.
Другие советы
Я не уверен, что это лучший подход, но я получил это на работу, используя рефлектор для обратного инженера Microsoft.Office.server.search.connector.bdc.bdcsecuritytrimmermer. Мне нужна только ценность идентичности, так что это немного упростить это.
Ниже приведен мой код, который принимает массив DocumentCrALLULS, предоставленных на триммеру безопасности, и переводит их в массив первичных ключей, как определено в моем файле модели BDC. Как только у меня есть те, которые я могу определить обрезку безопасности, используя более пользовательский код .NET.
В CheckCess () моего триммера безопасности (IsecurityTrimmermer2) у меня есть:
String[] ids = GetIds(documentCrawlUrls);
Тогда у меня есть следующий частный метод:
private string[] GetIds(IList<string> documentCrawlUrls)
{
string[] ids = new String[documentCrawlUrls.Count];
for (int i = 0; i < documentCrawlUrls.Count; i++)
{
try
{
string url = documentCrawlUrls[i];
Identity identity = null;
IEntity entity = null;
ILobSystemInstance lsi = null;
ParseUri(url, out entity, out identity, out lsi);
if (identity != null)
{
object[] values = identity.GetIdentifierValues();
if (values.Length > 0)
{
ids[i] = values[0].ToString();
}
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine("Error: " + ex.Message);
}
}
return ids;
}
Я не хотел переписать класс SPBDCuri, и это внутреннее, поэтому я обманываю отражением. В настоящее время я использую только один из параметров выхода, чтобы я мог улучшить эффективность. Я могу переписать порции SPBDCuri, которые мне нужны вместо того, чтобы прибегать к размышлению.
private void ParseUri(string crawlUri, out IEntity entity, out Identity identity, out ILobSystemInstance lsi)
{
//SPBdcUri uri = new SPBdcUri(new Uri(crawlUri));
AssemblyName assemblyName = new AssemblyName("Microsoft.Office.Server.Search.Connector, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
Assembly assembly = Assembly.Load(assemblyName);
Type spBdcUriType = assembly.GetType("Microsoft.Office.Server.Search.Connector.BDC.SPBDC.SPBdcUri");
object uri = Activator.CreateInstance(spBdcUriType,
BindingFlags.NonPublic | BindingFlags.Instance,
null, new object[] { new Uri(crawlUri) }, System.Globalization.CultureInfo.CurrentCulture);
//uri.DoOverrideBDCThrottlingLimits = false;
spBdcUriType.InvokeMember("DoOverrideBDCThrottlingLimits",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null, uri, new object[] { false });
//entity = uri.Entity;
object entityObj = spBdcUriType.InvokeMember("Entity",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
null, uri, null);
entity = (IEntity)entityObj;
//identity = uri.Identity;
object identityObj = spBdcUriType.InvokeMember("Identity",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
null, uri, null);
identity = (Identity)identityObj;
//lsi = uri.LobSystemInstance;
object lsiObj = spBdcUriType.InvokeMember("LobSystemInstance",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
null, uri, null);
lsi = (ILobSystemInstance)lsiObj;
}
О, вот мои «использование» заявления:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.BusinessData.MetadataModel.Collections;
using Microsoft.BusinessData.MetadataModel;
using Microsoft.BusinessData.Runtime;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.BusinessData.SharedService;
using Microsoft.Office.Server.Search.Query;