рдЖрдЗрдП, рдкреНрд░рдХреНрд╖реЗрдкрд┐рдд рддрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде QueryProvider рд╕реМрджрд╛ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВ

QueryProvider рдХреА рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛


QueryProvider рдЗрд╕рд╕реЗ рдирд╣реАрдВ рдирд┐рдкрдЯ рд╕рдХрддреЗ:


var result = _context.Humans .Select(x => $"Name: {x.Name} Age: {x.Age}") .Where(x => x != "") .ToList(); 

рдпрд╣ рдкреНрд░рдХреНрд╖реЗрдкрд┐рдд рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рд╕реА рднреА рд╡рд╛рдХреНрдп рдХреЗ рд╕рд╛рде рд╕реМрджрд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЖрд╕рд╛рдиреА рд╕реЗ рдЗрд╕рд╕реЗ рдирд┐рдкрдЯреЗрдЧрд╛:


 var result = _context.Humans .Select(x => "Name " + x.Name + " Age " + x.Age) .Where(x => x != "") .ToList(); 

рдХреНрд▓рд╛рдЗрдВрдЯрд▓реЗрд╡рд▓реНрдпреВрд╢рди (рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдХреИрд▓рдХреБрд▓реЗрд╢рди рдХреЗ рд▓рд┐рдП рдЕрдкрд╡рд╛рдж) рдХреЛ рдЪрд╛рд▓реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╕рдмрд╕реЗ рджрд░реНрджрдирд╛рдХ рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЪреВрдВрдХрд┐ рд╕рднреА рдСрдЯреЛрдореИрдкрд░ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдХреЛ рдкреНрд░рдХреНрд╖реЗрдк рдХреЗ рд▓рд┐рдП рд╕рдЦреНрддреА рд╕реЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдЗрдП рдЬрд╛рдиреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╣реИ рдФрд░ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╣рдорд╛рд░реЗ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ред


рдЪреАрдЬреЛрдВ рдХреЛ рдареАрдХ рдХрд░рдирд╛


рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдЯреНрд░реА рдореЗрдВ рдкреНрд░рдХреНрд╖реЗрдк рдЗрд╕ рддрд░рд╣ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрддрд╛ рд╣реИ (рдпрд╣ ExpressionStringBuilder.ExpressionToString рд╡рд┐рдзрд┐ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИ, рдпрд╣ рдХреБрдЫ рдиреЛрдбреНрд╕ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдареАрдХ рд╣реИ):


 // boxing is required for x.Age Format("Name:{0} Age:{1}", x.Name, Convert(x.Age, Object))) 

рдпрд╛ рдЗрд╕ рддрд░рд╣, рдЕрдЧрд░ 3 рд╕реЗ рдЕрдзрд┐рдХ рддрд░реНрдХ рд╣реИрдВ:


 Format("Name:{0} Age:{1}", new [] {x.Name, Convert(x.Age, Object))) 

рд╣рдо рдпрд╣ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░рджрд╛рддрд╛ рдХреЛ рдЗрди рдорд╛рдорд▓реЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд╕рд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдпрд╣ рдЗрди рдорд╛рдорд▓реЛрдВ рдХреЛ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЬреНрдЮрд╛рдд ToString () рдХреЗ рд╕рд╛рде рд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд┐рдЦрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:


 ((("Name: " + x.Name) + " Age: ") + Convert(x.Age, Object))) 

рдореИрдВ рдПрдХ рд╡рд┐рдЬрд╝рд┐рдЯрд░ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдЯреНрд░реА (рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, MethodCallExpression рдиреЛрдбреНрд╕) рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдЧрд╛ рдФрд░ рдкреНрд░рд╛рд░реВрдкрдг рд╡рд┐рдзрд┐ рдХреЛ рд╕реНрдерд╛рдирд╛рдкрдиреНрди рдХреЗ рд╕рд╛рде рдмрджрд▓ рджреЗрдЧрд╛ред рдпрджрд┐ рдЖрдк рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдкреЗрдбрд╝реЛрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ, рддреЛ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ C # рдкреЗрдбрд╝ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЖрдЧрдВрддреБрдХ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ - рдПрдХреНрд╕рдкреНрд░реЗрд╢рдирд╡рд┐рдЬрд░ ред рд░реБрдЪрд┐ рд░рдЦрдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА ред


рд╣рдо рд╕рднреА рдХреА рдЬрд░реВрд░рдд рд╣реИ VisitMethodCall рд╡рд┐рдзрд┐ рд╕реЗ рд╣рдЯрдХрд░ рдФрд░ рд▓реМрдЯреЗ рдореВрд▓реНрдп рдХреЛ рдереЛрдбрд╝рд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИред рд╡рд┐рдзрд┐ рдкреИрд░рд╛рдореАрдЯрд░ MethodCallExpression рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╡рд┐рдзрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдФрд░ рдЙрд╕реЗ рджрд┐рдП рдЧрдП рддрд░реНрдХреЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдЖрдЗрдП рдХрд╛рд░реНрдп рдХреЛ рдХрдИ рднрд╛рдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВ:


  1. рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдВ рдХрд┐ рдпрд╣ рдкреНрд░рд╛рд░реВрдк рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ рдХрд┐ VisitMethodCall рдореЗрдВ рдЖрдпрд╛ рд╣реИ;
  2. рд╡рд┐рдзрд┐ рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХреЗ рд╕рд╛рде рдмрджрд▓реЗрдВ;
  3. рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдореМрдЬреВрдж рдкреНрд░рд╛рд░реВрдк рдкрджреНрдзрддрд┐ рдХреЗ рд╕рднреА рдЕрдзрд┐рднрд╛рд░ рд╕рдВрднрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ;
  4. рд╣рдорд╛рд░реЗ рдЖрдЧрдВрддреБрдХ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╕реНрддрд╛рд░ рд╡рд┐рдзрд┐ рд▓рд┐рдЦреЗрдВред

рдкрд╣рд▓рд╛ рднрд╛рдЧ рд╕рд░рд▓ рд╣реИ: рдкреНрд░рд╛рд░реВрдк рд╡рд┐рдзрд┐ рдореЗрдВ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдЯреНрд░реА рдореЗрдВ рдирд┐рд░реНрдорд┐рдд 4 рдЕрдзрд┐рднрд╛рд░ рд╣реИрдВ:


  public static string Format(string format, object arg0) public static string Format(string format, object arg0,object arg1) public static string Format(string format, object arg0,object arg1,object arg2) public static string Format(string format, params object[] args) 

рдЪрд▓реЛ рдЙрдиреНрд╣реЗрдВ рдирд┐рдХрд╛рд▓рдиреЗ, рдЙрдирдХреЗ MethodInfo рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░:


 private IEnumerable<MethodInfo> FormatMethods => typeof(string).GetMethods().Where(x => x.Name.Contains("Format")) //first three private IEnumerable<MethodInfo> FormatMethodsWithObjects => FormatMethods .Where(x => x.GetParameters() .All(xx=> xx.ParameterType == typeof(string) || xx.ParameterType == typeof(object))); //last one private IEnumerable<MemberInfo> FormatMethodWithArrayParameter => FormatMethods .Where(x => x.GetParameters() .Any(xx => xx.ParameterType == typeof(object[]))); 

рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛ред рдЕрдм рд╣рдо рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ MethodCallExpression рдореЗрдВ рдкреНрд░рд╛рд░реВрдк рд╡рд┐рдзрд┐ "рдЖрдпрд╛ рдерд╛"ред


VisitMethodCall рдореЗрдВ рдкреЗрдбрд╝ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░рддреЗ рд╣реБрдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рдзрд┐рдпрд╛рдБ рдЖ рд╕рдХрддреА рд╣реИрдВ:


  1. рдСрдмреНрдЬреЗрдХреНрдЯ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рд░реВрдк
  2. рд╡рд╕реНрддреБ [] рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рд░реВрдк
  3. рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреБрдЫ рдФрд░ред

рдХрд╕реНрдЯрдо рдкреИрдЯрд░реНрди рдХрд╛ рдПрдХ рд╕рд╛ рдорд┐рд▓рд╛рди

рдЪреВрдБрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ 3 рд╕реНрдерд┐рддрд┐рдпрд╛рдБ рд╣реИрдВ, рд╣рдо рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрднрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЬрдм рд╕реЗ рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╣рдореЗрдВ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд╕рднреА рдорд╛рдорд▓реЛрдВ рдХреЛ рдЗрд╕ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рд▓реЛрдб рдХрд░ рджреЗрдВрдЧреЗ:


 public class PatternMachingStructure { public Func<MethodInfo, bool> FilterPredicate { get; set; } public Func<MethodCallExpression, IEnumerable<Expression>> SelectorArgumentsFunc { get; set; } public Func<MethodCallExpression, IEnumerable<Expression>, Expression> ReturnFunc { get; set; } } var patternMatchingList = new List<PatternMachingStructure>() 

FilterPredicate рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рдо рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдЙрди 3 рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╕реЗ рдХрд┐рд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВред SelectorArgumentFunc рдХреЛ рдлреЙрд░реНрдореЗрдЯ рдкрджреНрдзрддрд┐ рдХреЗ рд╕рднреА рддрд░реНрдХреЛрдВ рдХреЛ рдПрдХреАрдХреГрдд рдЖрдХрд╛рд░ рдореЗрдВ рд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, ReturnFunc рд╡рд┐рдзрд┐, рдЬреЛ рдкреВрд░реНрдг рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд▓реМрдЯрд╛рдПрдЧрд╛ред


рдЕрдм рдЖрдЗрдП рдкреНрд░рдХреНрд╖реЗрдк рдХреЛ рд╕реНрдерд╛рдирд╛рдкрдиреНрдирддрд╛ рд╕реЗ рдмрджрд▓реЗрдВ, рдФрд░ рдЙрд╕рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:


 private Expression InterpolationToStringConcat(MethodCallExpression node, IEnumerable<Expression> formatArguments) { //picking the first argument //(example : Format("Name: {0} Age: {1}", x.Name,x.Age) -> //"Name: {0} Age: {1}" var formatString = node.Arguments.First(); // going through the pattern from Format method and choosing every // line between the arguments and pass them to the ExpressionConstant method // example:->[Expression.Constant("Name: "),Expression.Constant(" Age: ")] var argumentStrings = Regex.Split(formatString.ToString(),RegexPattern) .Select(Expression.Constant); // merging them with the formatArguments values // example ->[ConstantExpression("Name: "),PropertyExpression(x.Name), // ConstantExpression("Age: "), // ConvertExpression(PropertyExpression(x.Age), Object)] var merge = argumentStrings.Merge(formatArguments, new ExpressionComparer()); // merging like QueryableProvider merges simple lines concatenation // example : -> MethodBinaryExpression //(("Name: " + x.Name) + "Age: " + Convert(PropertyExpression(x.Age),Object)) var result = merge.Aggregate((acc, cur) => Expression.Add(acc, cur, StringConcatMethod)); return result; } 

InterpolationToStringConcat рдЖрдЧрдВрддреБрдХ рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, ReturnFunc рдХреЗ рдкреАрдЫреЗ рдЫрд┐рдкрд╛ рд╣реЛрдЧрд╛ :


 protected override Expression VisitMethodCall(MethodCallExpression node) { var pattern = patternMatchingList.First(x => x.FilterPredicate(node.Method)); var arguments = pattern.SelectorArgumentsFunc(node); var expression = pattern.ReturnFunc(node, arguments); return expression; } 

рдЕрдм рд╣рдореЗрдВ рд╕рднреА рдкреНрд░рд╛рд░реВрдк рд╡рд┐рдзрд┐ рдЕрдзрд┐рднрд╛рд░ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдмрд▓реНрдХрд┐ рддреБрдЪреНрдЫ рд╣реИ рдФрд░ рдкреИрдЯрд░реНрди рдХреЗ рдЕрдВрджрд░ рд╕реНрдерд┐рдд рд╣реИред


 patternMatchingList = new List<PatternMachingStructure> { // first three Format overloads new PatternMachingStructure { FilterPredicate = x => FormatMethodsWithObjects.Contains(x), SelectorArgumentsFunc = x => x.Arguments.Skip(1), ReturnFunc = InterpolationToStringConcat }, // last Format overload receiving the array new PatternMachingStructure { FilterPredicate = x => FormatMethodWithArrayParameter.Contains(x), SelectorArgumentsFunc = x => ((NewArrayExpression) x.Arguments.Last()) .Expressions, ReturnFunc = InterpolationToStringConcat }, // node.Method != Format new PatternMachingStructure() { FilterPredicate = x => FormatMethods.All(xx => xx != x), SelectorArgumentsFunc = x => x.Arguments, ReturnFunc = (node, _) => base.VisitMethodCall(node) } }; 

рддрджрдиреБрд╕рд╛рд░, рд╣рдо рдкрд╣рд▓реЗ рд╕рдХрд╛рд░рд╛рддреНрдордХ FilterPredicate рддрдХ VisitMethodCall рдкрджреНрдзрддрд┐ рдореЗрдВ рдЙрд╕ рд╕реВрдЪреА рдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░реЗрдВрдЧреЗ, рдлрд┐рд░ рддрд░реНрдХреЛрдВ ( SelectorArgumentFunc ) рдореЗрдВ рдХрдирд╡рд░реНрдЯ рдХрд░реЗрдВ рдФрд░ ReturnFunc рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ ред


рдЖрдЗрдП рдПрдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╡рд┐рдзрд┐ рд▓рд┐рдЦреЗрдВ рдЬрд┐рд╕реЗ рд╣рдо рдкреНрд░рдХреНрд╖реЗрдк рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рд╣рдо рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕реЗ рд╡рд┐рдЬрд╝рд┐рдЯрд░ рдХреЛ рд╕реМрдВрдк рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдореВрд▓ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдЯреНрд░реА рдХреА рдЬрдЧрд╣ CreateQuery рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 public static IQueryable<T> ReWrite<T>(this IQueryable<T> qu) { var result = new InterpolationStringReplacer<T>().Visit(qu.Expression); var s = (IQueryable<T>) qu.Provider.CreateQuery(result); return s; } 

рдЕрдкрдирд╛ рдзреНрдпрд╛рди qu.Provider.CreateQuery (рдкрд░рд┐рдгрд╛рдо) рдХреЛ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рджреЗрдВ , рдЬрд┐рд╕рдореЗрдВ IQueryable <T> рдореЗрдВ IQueryable рд╡рд┐рдзрд┐ рд╣реИ ред рдпрд╣ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ C # рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ( IEnumerable <T> рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рджреЗрдЦреЗрдВ!), рдФрд░ рдпрд╣ рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рд╕рднреА рд╕рд╛рдорд╛рдиреНрдп рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕реЗ рдЖрдпрд╛ рд╣реИ рдЬреЛ IQueryable / IEnumerable рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдЕрдиреНрдп рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрднрд╛рд▓рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИред


рдЯреА рдХреЛ рдПрдХ рдмреЗрд╕рдХрд▓реИрд╕ (рдХреЛрд╡рд░рд┐рдпрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рддрдХ рд▓рд╛рдиреЗ рд╕реЗ рд╣рдо рдмрдЪ рд╕рдХрддреЗ рдереЗ, рд▓реЗрдХрд┐рди рдпрд╣ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рддрд░реАрдХреЛрдВ рдкрд░ рдХреБрдЫ рд╕реАрдорд╛рдПрдБ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред


рдкрд░рд┐рдгрд╛рдо


рд▓реЗрдЦ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ linq рд╡реНрдпрдВрдЬрдХ рдореЗрдВ рдкреБрдирдГ рд▓рд╛рдЧреВ рдХрд░реЗрдВ:


 var result = _context.Humans .Select(x => $"Name: {x.Name} Age: {x.Age}") .Where(x => x != "") .ReWrite() .ToList(); // correct // [Name: "Piter" Age: 19] 

GitHub

Source: https://habr.com/ru/post/hi454860/


All Articles