如何从 BDC URL 加载 BDC 数据?

发布于 2024-09-25 04:10:12 字数 974 浏览 7 评论 0原文

我在 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=07nk0004080g10003o03v vf

我需要获取该对象的属性(实际上只是主键值) 。知道如何使用 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 年文档声称是这样做的),似乎效率也很低。我想我更愿意将信息批量处理到单个 Web 服务调用中,但我持观望态度......

I am doing this in SharePoint 2010, but wouldn't be surprised if the problem exists in SharePoint 2007 and has the same solution.

I have a runtime security trimmer on my BDC data. I was expecting the security trimmer to give me URLs based off of the "default" profile URL defined in the model. Unfortunately, that is not the case. It gives me a URL like:
bdc3://amms_amms/default/00000000%252d0000%252d0000%252d0000%252d000000000000/1971/amms/1973?s_id=ibqaaaaaaaaa=&s_ce=07nk0004080g10003o03vvf

I need to get the properties of this object (really just the primary key value). Any idea how I do this with the BDC object model? The following link seems to provide some help, but I haven't seen anything that consumes the URL above.

http://msdn.microsoft.com/en-us/library/ee556400.aspx


Update: I see that SharePoint 2007 has an AccessChecker (http://msdn.microsoft.com/en-us/library/aa981124.aspx) and 2010 likely has this as well (can't find good documentation for 2010 on this). We can't easily have security descriptors in the database, but the AccessChecker method might suffice.

Digging a little further I see that Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer is what is likely what is used by the AccessChecker in SharePoint 2010. It appears that this does a query to the DB per URL. Seems inefficient even if it does do it on multiple threads (which the 2007 documentation claims to do). I think I would prefer to batch up the information into a single web service call, but am on the fence...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

驱逐舰岛风号 2024-10-02 04:10:12

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

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,但不适用于其他 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 个都是正确的。

OK, here's a simplification of my previous answer. It appears that you can totally avoid reflection:

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

Note that I tried avoiding using the UriParser from Microsoft.Office.Server.Search.Connector using code like:

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

Unfortunately, this worked for some Id's and not others. I decided not to investigate any further and just use the special UriParser. In one example the ids I was looking for were "5,20,21,7,8,6,14,19,17,18,4" but this second approach gave me "5,20,21,24581,8,24580,24588,24593,17,24592,4". That messed me up for a few minutes since the first 3 were correct.

掩饰不了的爱 2024-10-02 04:10:12

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

下面是我的代码,它获取提供给安全修剪器的 documentCrawlUrl 数组,并将它们转换为我的 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;

I'm not sure it is the best approach, but I got this to work by using Reflector to reverse engineer Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer. I only needed the identity value so that simplified this a little.

Below is my code that takes an array of documentCrawlUrls provided to the security trimmer and translates them into an array of primary keys as defined in my BDC model file. Once I have those I can determine the security trimming using more custom .NET code.

In CheckAccess() of my security trimmer (ISecurityTrimmer2) I have:

String[] ids = GetIds(documentCrawlUrls);

Then I have the following private method:

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

I didn't want to rewrite the SPBdcUri class and it is internal, so I cheat with reflection. I currently only use one of the out parameters so I can improve on efficiency. I may re-write the portions of SPBdcUri that I need instead of resorting to reflection.

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

Oh, here's my "using" statements:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文