如何从BDC URL加载BDC数据?

时间:2010-09-28 21:20:31

标签: sharepoint bdc bcs

我在SharePoint 2010中执行此操作,但如果SharePoint 2007中存在此问题且具有相同的解决方案,则不会感到惊讶。

我的BDC数据上有运行时安全修整程序。我期待安全修整程序根据模型中定义的“默认”配置文件URL为我提供URL。不幸的是,事实并非如此。它给了我一个URL:    bdc3:// amms_amms / default / 00000000%252d0000%252d0000%252d0000%252d000000000000 / 1971 / amms / 1973?s_id = ibqaaaaaaaaa =& 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.BdcSecurityTrimmer可能是SharePoint 2010中AccessChecker使用的内容。看来这会对每个URL的数据库进行查询。即使它确实在多个线程上执行它(2007年文档声称要这样做),似乎效率低下。我想我更愿意将这些信息批量发送到一个网络服务电话中,但我还是准备好了......

2 个答案:

答案 0 :(得分:1)

好的,这是我以前的答案的简化。看来你可以完全避免反思:

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;
}

请注意,我尝试使用以下代码避免使用Microsoft.Office.Server.Search.Connector中的UriParser:

string id = HttpUtility.ParseQueryString(new Uri(url).Query)["s_id"];
ids[i] = Identity.Deserialize(id.ToUpper()).GetIdentifierValues()[0].ToString();

不幸的是,这适用于某些Id而非其他人。我决定不进一步调查,只使用特殊的UriParser。在一个例子中,我正在寻找的ids是“5,20,21,7,8,6,14,19,17,18,4”,但第二种方法给了我“5,20,21,24581,8, 24580,24588,24593,17,24592,4" 。因为前3个是正确的,这让我搞砸了几分钟。

答案 1 :(得分:0)

我不确定这是最好的方法,但我通过使用Reflector对Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer进行逆向工程来实现这一点。我只需要身份值,以便稍微简化一下。

下面是我的代码,它将一个documentCrawlUrls数组提供给安全修整程序,并将它们转换为我的BDC模型文件中定义的主键数组。有了这些,我可以使用更多的自定义.NET代码来确定安全修整。

在我的安全修整器(ISecurityTrimmer2)的CheckAccess()中,我有:

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;