Как использовать выражение с нулевым полем с mongo - PullRequest
1 голос
/ 19 июня 2020

добрый день, у меня проблема с mon go db и linq. например: у меня есть класс заказа:

class Order
{
    public virtual int Id { get; set; }
    public virtual int FactoryId { get; set; }
}

каждый заказ принадлежит одному из заводов (через поле FactoryId)

теперь у меня есть текущий пользователь:

class User
{
    public virtual int Id { get; set; }
    public virtual Factory Factory { get; set; }
}

Пользователь может быть связан с фабрикой или может быть общесистемным (доступ ко всем фабрикам, поэтому Factory имеет значение null)

сейчас, я хочу получить все заказы, к которым текущий пользователь может получить доступ:

var orders = db
    .GetCollection<Order>("order").AsQueryable()
    .Where(x => currentUser.Factory == null || x.FactoryId == currentUser.Factory.Id)
    .ToArray();

и если у текущего пользователя нет factory (factory = null), то я получил исключение: System.Reflection.TargetException: для нестандартного c метода требуется цель.

с трассировкой стека:

   at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
   at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
   at System.Reflection.PropertyInfo.GetValue(Object obj)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.ReflectionEvaluator.VisitMember(MemberExpression node)
   at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.ReflectionEvaluator.Evaluate(Expression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.EvaluateSubtree(Expression subtree)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
   at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
   at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 node)
   at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression node)
   at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
   at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Evaluate(Expression node)
   at MongoDB.Driver.Linq.MongoQueryProviderImpl`1.Prepare(Expression expression)
   at MongoDB.Driver.Linq.MongoQueryProviderImpl`1.Translate(Expression expression)
   at MongoDB.Driver.Linq.MongoQueryProviderImpl`1.Execute(Expression expression)
   at MongoDB.Driver.Linq.MongoQueryableImpl`2.GetEnumerator()
   at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at ConsoleApp1.Program.Main(String[] args) in D:\ConsoleApp1\ConsoleApp1\Program.cs:line 45

я создаю образец для воспроизведения этого поведения: https://dotnetfiddle.net/iFIkrA

если я меняю пользователя на пользователя, который привязан к фабрике - все работает нормально

, поэтому я не Не понимаю, что я пропустил

Я использовал net ядро ​​3.1 с mongodb.driver 2.10.4

1 Ответ

0 голосов
/ 19 июня 2020

Это происходит из-за того, что вы пытаетесь получить доступ к свойству нулевого объекта:

x.FactoryId == currentUser.Factory.Id

Итак, чтобы решить эту проблему, мы можем проверить, имеет ли свойство Factory значение null, и установить ли оно другое значение, не будет найден в базе данных, например -1, и если он отличается от нуля, мы можем присвоить его идентификатор. Пример ниже:

        var currentUser = new User();
        var factoryId = currentUser.Factory == null ? -1 : currentUser.Factory.Id;
        //Now exception should not be thrown
        var orders = db
            .GetCollection<Order>("orders").AsQueryable()
            .Where(x => currentUser.Factory == null || 
                   x.FactoryId == factoryId)
            .ToArray();
...