Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检测ClientObject属性是否已检索/初始化的正确方法_C#_Sharepoint_Csom - Fatal编程技术网

C# 检测ClientObject属性是否已检索/初始化的正确方法

C# 检测ClientObject属性是否已检索/初始化的正确方法,c#,sharepoint,csom,C#,Sharepoint,Csom,如果您使用的是SharePoint和access属性中的客户端对象模型,而这些属性尚未初始化或已由 Context.Load(property); Context.ExecuteQuery(); 例如,你会得到一个: Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException 或 集合尚未初始化。没有收到任何请求或请求 请求尚未执行 例外 在访问这些属性之前,如果它们已经初始化/检索,是否有适当的方法进行检查?没有尝试

如果您使用的是SharePoint和access属性中的客户端对象模型,而这些属性尚未初始化或已由

Context.Load(property); 
Context.ExecuteQuery();
例如,你会得到一个:

Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException

集合尚未初始化。没有收到任何请求或请求 请求尚未执行

例外

在访问这些属性之前,如果它们已经初始化/检索,是否有适当的方法进行检查?没有尝试/抓住的方法。我不喜欢那个

我想在抛出异常之前进行检查并处理它

我已经查过了


方法,但它们没有真正的帮助
IsPropertyAviable
仅检查标量属性,不会在例如
Web上给出结果。Lists
IsObjectPropertyInstantiated
对于
Web.Lists
返回true,尽管
Web.Lists
未初始化。

我想说您的问题已经包含了一些问题的正确答案范围

为了确定是否加载了客户端对象属性,可以使用以下方法:

  • 方法指示是否 已检索或设置指定的标量属性
  • 表明 是否实例化客户端对象的指定属性
测验 测试用例1:仅加载标量属性

ctx.Load(ctx.Web, w => w.Title);
ctx.ExecuteQuery();
//Results:
ctx.Web.IsObjectPropertyInstantiated("Lists")  False
ctx.Web.IsPropertyAvailable("Title")    True
ctx.Load(ctx.Web, w => w.Lists);
ctx.ExecuteQuery();
//Results:
ctx.Web.IsObjectPropertyInstantiated("Lists")  True
ctx.Web.IsPropertyAvailable("Title")    False
测试用例2:仅加载复合属性

ctx.Load(ctx.Web, w => w.Title);
ctx.ExecuteQuery();
//Results:
ctx.Web.IsObjectPropertyInstantiated("Lists")  False
ctx.Web.IsPropertyAvailable("Title")    True
ctx.Load(ctx.Web, w => w.Lists);
ctx.ExecuteQuery();
//Results:
ctx.Web.IsObjectPropertyInstantiated("Lists")  True
ctx.Web.IsPropertyAvailable("Title")    False
测试用例3:同时加载标量和复合属性

ctx.Load(ctx.Web, w=>w.Lists,w=>w.Title);
ctx.ExecuteQuery();
//Results
ctx.Web.IsObjectPropertyInstantiated("Lists")  True
ctx.Web.IsPropertyAvailable("Title")    True


如何动态确定是否加载了客户端对象属性? 由于和方法希望将属性名指定为字符串值,这可能会导致键入错误,因此我通常更喜欢以下内容:


Vadim Gremyachev提供的测试只覆盖了一半的场景——您使用的是ctx.Load。但使用ctx.LoadQuery时,结果会发生变化:

var query = from lst in ctx.Web.Lists where lst.Title == "SomeList" select lst;
var lists = ctx.LoadQuery(query);
ctx.ExecuteQuery();
ctx.Web.IsObjectPropertyInstantiated("Lists") -> True
ctx.Web.Lists.ServerObjectIsNull -> False
ctx.Web.Lists.Count -> CollectionNotInitializedException
因此,一旦对集合调用了LoadQuery,就无法再看到该集合是否实际可用


在这种情况下,唯一的方法是检测异常的发生。

使用扩展的想法很好,但只适用于列表。扩展可以在“对象”和“标量”属性之间进行选择。我认为这样比扩建更好:

public static bool IsPropertyAvailableOrInstantiated<T>(this T clientObject, Expression<Func<T, object>> property)
    where T : ClientObject
{
    var expression = (MemberExpression)property.Body;
    var propName = expression.Member.Name;
    var isObject = typeof(ClientObject).IsAssignableFrom(property.Body.Type); // test with ClientObject instead of ClientObjectList
    return isObject ? clientObject.IsObjectPropertyInstantiated(propName) : clientObject.IsPropertyAvailable(propName);
}

公共静态bool isPropertyAvailable或Installated(此T clientObject、Expression属性)
其中T:ClientObject
{
变量表达式=(MemberExpression)property.Body;
var propName=expression.Member.Name;
var isObject=typeof(ClientObject).IsAssignableFrom(property.Body.Type);//使用ClientObject而不是ClientObjectList进行测试
返回isObject?clientObject.IsObjectPropertyInstantiated(propName):clientObject.IsPropertyAvailable(propName);
}

好的,这变得越来越复杂,尤其是在SharePoint Online中,即使没有抛出异常,加载和执行方法的结果也可能不完整。但是,下面是我从这个线程和其他线程中收集的内容,这些线程组合到一个LoadAndExecute方法中,该方法可以是ClientContext类的子类扩展,也可以转换为静态扩展类。对于新的客户端对象,对象及其属性将在一个操作中加载,但结果将针对每个属性分别进行检查。对于现有客户端对象,在单独的操作中只加载缺少的属性,这可能会不必要地消耗网络资源。因此,该方法不仅检查哪些属性未初始化,还尝试检索缺少的属性。此外,还有另一个主题是通过重写ClientContext的Execute方法来避免被限制,但这里不包括:

/// <summary>
/// An extended ClientContext to avoid getting throttled.
/// </summary>
public partial class OnlineContext : ClientContext
{
    /// <inheritdoc />
    public OnlineContext(string webFullUrl, int retryCount = 0, int delay = 0)
        : base(webFullUrl)
    {
        RetryCount = retryCount;
        Delay = delay;
    }

    /// <summary>
    /// The retry count.
    /// </summary>
    public int RetryCount { get; set; }

    /// <summary>
    /// The delay between attempts in seconds.
    /// </summary>
    public int Delay { get; set; }

    /// <summary>
    /// Loads and executes the specified client object properties.
    /// </summary>
    /// <typeparam name="T">the object type.</typeparam>
    /// <param name="clientObject">the object.</param>
    /// <param name="properties">the properties.</param>
    /// <returns>true if all available, false otherwise.</returns>
    public bool LoadAndExecute<T>(T clientObject, params Expression<Func<T, object>>[] properties)
        where T : ClientObject
    {
        int retryAttempts = 0;
        int backoffInterval = Math.Max(Delay, 1);

        bool retry;
        bool available;
        do
        {
            if (clientObject is ClientObjectCollection)
            {
                // Note that Server Object can be null for collections!
                ClientObjectCollection coc = (ClientObjectCollection) (ClientObject) clientObject;
                if (!coc.ServerObjectIsNull.HasValue || !coc.ServerObjectIsNull.Value)
                {
                    available = coc.AreItemsAvailable;
                }
                else
                {
                    available = false;
                    break;
                }
            }
            else if (clientObject.ServerObjectIsNull.HasValue)
            {
                available = !clientObject.ServerObjectIsNull.Value;
                break;
            }
            else
            {
                available = false;
            }

            if (!available && retryAttempts++ <= RetryCount)
            {
                if (retryAttempts > 1)
                {
                    Thread.Sleep(backoffInterval * 1000);
                    backoffInterval *= 2;
                }

                Load(clientObject, properties);
                ExecuteQuery();
                retry = true;
            }
            else
            {
                retry = false;
            }
        } while (retry);

        if (available)
        {
            if (properties != null && properties.Length > 0)
            {
                foreach (Expression<Func<T, object>> property in properties)
                {
                    if (!LoadAndExecuteProperty(clientObject, property, retryAttempts > 0))
                    {
                        available = false;
                    }
                }
            }
        }
        return available;
    }

    /// <summary>
    /// Loads and executes the specified client object property.
    /// </summary>
    /// <typeparam name="T">the object type.</typeparam>
    /// <param name="clientObject">the object.</param>
    /// <param name="property">the property.</param>
    /// <param name="loaded">true, if the client object was already loaded and executed at least once.</param>
    /// <returns>true if available, false otherwise.</returns>
    private bool LoadAndExecuteProperty<T>(T clientObject, Expression<Func<T, object>> property, bool loaded = false)
        where T : ClientObject
    {
        string propertyName;
        bool isObject;
        bool isCollection;
        Func<T, object> func;
        Expression expression = property.Body;
        if (expression is MemberExpression)
        {
            // Member expression, check its type to select correct property test.
            propertyName = ((MemberExpression) expression).Member.Name;
            isObject = typeof(ClientObject).IsAssignableFrom(property.Body.Type);
            isCollection = isObject
                ? typeof(ClientObjectCollection).IsAssignableFrom(property.Body.Type)
                : false;
            func = isObject ? property.Compile() : null;
        }
        else if (!loaded)
        {
            // Unary expression or alike, test by invoking its function.
            propertyName = null;
            isObject = false;
            isCollection = false;
            func = property.Compile();
        }
        else
        {
            // Unary expression and alike should be available if just loaded.
            return true;
        }

        int retryAttempts = 0;
        int backoffInterval = Math.Max(Delay, 1);

        bool retry;
        bool available;
        do
        {
            if (isObject)
            {
                if (clientObject.IsObjectPropertyInstantiated(propertyName))
                {
                    ClientObject co = (ClientObject) func.Invoke(clientObject);
                    if (isCollection)
                    {
                        ClientObjectCollection coc = (ClientObjectCollection) co;
                        if (!coc.ServerObjectIsNull.HasValue || !coc.ServerObjectIsNull.Value)
                        {
                            available = coc.AreItemsAvailable;
                        }
                        else
                        {
                            available = false;
                            break;
                        }
                    }
                    else if (co.ServerObjectIsNull.HasValue)
                    {
                        available = !co.ServerObjectIsNull.Value;
                        break;
                    }
                    else
                    {
                        available = false;
                    }
                }
                else
                {
                    available = false;
                }
            }
            else if (propertyName != null)
            {
                available = clientObject.IsPropertyAvailable(propertyName);
            }
            else if (func != null)
            {
                try
                {
                    func.Invoke(clientObject);
                    available = true;
                }
                catch (PropertyOrFieldNotInitializedException)
                {
                    available = false;
                }
            }
            else
            {
                available = true; // ?
            }

            if (!available && retryAttempts++ <= RetryCount)
            {
                if (retryAttempts > 1)
                {
                    Thread.Sleep(backoffInterval * 1000);
                    backoffInterval *= 2;
                }

                Load(clientObject, property);
                ExecuteQuery();
                retry = true;
            }
            else
            {
                retry = false;
            }
        } while (retry);
        return available;
    }
}
//
///一个扩展的ClientContext,以避免被限制。
/// 
公共部分类OnlineContext:ClientContext
{
/// 
公共OnlineContext(字符串webFullUrl,int-retryCount=0,int-delay=0)
:base(webFullUrl)
{
RetryCount=RetryCount;
延迟=延迟;
}
/// 
///重试计数。
/// 
public int RetryCount{get;set;}
/// 
///两次尝试之间的延迟(以秒为单位)。
/// 
公共整数延迟{get;set;}
/// 
///加载并执行指定的客户端对象属性。
/// 
///对象类型。
///物体。
///属性。
///如果全部可用,则为true,否则为false。
public bool LoadAndExecute(T clientObject,params Expression[]属性)
其中T:ClientObject
{
int-retryAttempts=0;
int backoffInterval=Math.Max(延迟,1);
布尔重试;
bool可用;
做
{
if(clientObject是clientObject集合)
{
//请注意,对于集合,服务器对象可以为null!
ClientObjectCollection coc=(ClientObjectCollection)(ClientObject)ClientObject;
如果(!coc.serverobjectisnll.HasValue | |!coc.serverobjectisnl.Value)
{
可用=coc.AreItemsAvailable;
}
其他的
{
可用=错误;
打破
}
}
else if(clientObject.serverobjectisnll.HasValue)
{
可用=!clientObject.ServerObjectsAll.Value;
打破
}
其他的
{
可用=错误;
}
如果(!available&&retryAttempts++1)
{
线程睡眠(BackofInterval*1000);
BackofInterval*=2;
}
加载(客户端对象、属性);
ExecuteQuery();
重试=真;
}
其他的
{
重试=错误;