Google Datastore - это база данных NoSQL, которая работает с сущностями, а не с таблицами. Вам нужно загрузить все «записи», которые являются «ключевыми идентификаторами», в Datastore и все их «свойства», то есть «столбцы», которые вы видите в консоли. Но вы хотите загрузить их на основе «доброго» имени, которое является «таблицей», на которую вы ссылаетесь.
Ниже приведено решение о том, как извлечь все идентификаторы ключей и их свойства из хранилища данных с помощью облачной функции HTTP-триггера, работающей в среде Node.js 8.
{
"name": "sample-http",
"version": "0.0.1",
"dependencies": {
"@google-cloud/datastore": "^3.1.2"
}
}
loadDataFromDatastore
, так как это имя функции, которую мы хотим выполнить. ПРИМЕЧАНИЕ. При этом все загруженные записи будут записываться в журналы Stackdriver функции Cloud. Ответом для каждой записи является JSON, поэтому вам придется преобразовать ответ в объект JSON, чтобы получить нужные данные. Получите идею и измените код соответствующим образом.
BLOCKQUOTE>
Это смутило меня уже... обычно, Вы думаете, объединяют действие на его значения - я предположил что первый непустой указатель (f) => f.Value
, и "default value"
был бы возвращен, который не имеет место (пустой тест находится на инициирующем экземпляре).
Обратите внимание, что это было бы более ясно без скобок?
f => f.Value
То, что Вы на самом деле делаете, подобно Select
- так что-то как SafeSelect
было бы хорошее имя, IMO (но возможно не точно это...).
Или даже просто Dereference
, пока имя аргумента (и т.д.) проясняет, для чего второй аргумент.
Да, я понял бы это. Да, объедините, хорошее имя. Да, было бы лучше, если бы C# имел пустой безопасный оператор разыменования как Groovy и некоторые другие языки :)
Обновление
C# 6 имеет такой оператор - пустой условный оператор, ?.
Например:
var street = customer?.PrimaryAddress?.Street;
Используйте его в сочетании с исходным объединяющим пустой указатель оператором, если Вы все еще хотите значение по умолчанию. Например:
var street = customer?.PrimaryAddress?.Street ?? "(no address given)";
Или, на основе исходного кода в вопросе:
Console.WriteLine(getSomeFoo()?.Value ?? "default");
Отмечание, конечно, что, предоставляя значению по умолчанию этот путь работает, только если он должен хорошо использовать то значение по умолчанию, даже когда заключительное значение свойства доступно, но устанавливается в NULL по некоторым причинам.
Результат выражения x?.y
null
если x
оценивает к пустому указателю; иначе это - результат x.y
. О, и можно использовать его для условного вызова метода, также:
possiblyNull?.SomeMethod();
Это могло легко быть расширено также:
public static TResult Coalesce<T, TResult>(this T obj, Func<T, TResult> func, TResult defaultValue)
{
if (obj == null)
return defaultValue;
return func(obj);
}
public static TResult Coalesce<T1, T2, TResult>(this T1 obj, Func<T1, T2> func1, Func<T2, TResult> func2, TResult defaultValue)
{
if (obj == null)
return defaultValue;
T2 obj2 = func1(obj);
if (obj2 == null)
return defaultValue;
return func2(obj2);
}
public static TResult Coalesce<T1, T2, T3, TResult>(this T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, TResult> func3, TResult defaultValue)
{
if (obj == null)
return defaultValue;
T2 obj2 = func1(obj);
if (obj2 == null)
return defaultValue;
T3 obj3 = func2(obj2);
if (obj3 == null)
return defaultValue;
return func3(obj3);
}
public static TResult Coalesce<T1, T2, T3, T4, TResult>(this T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, T4> func3, Func<T4, TResult> func4, TResult defaultValue)
{
if (obj == null)
return defaultValue;
T2 obj2 = func1(obj);
if (obj2 == null)
return defaultValue;
T3 obj3 = func2(obj2);
if (obj3 == null)
return defaultValue;
T4 obj4 = func3(obj3);
if (obj4 == null)
return defaultValue;
return func4(obj4);
}
Который мог использоваться как это:
BinaryTreeNode node = LocateNode(someKey);
BinaryTreeNode grandFatherNode = node.Coalesce(n1 => n1.Parent, n2 => n2.Parent, null);
Который заменил бы:
BinaryTreeNode grandFatherNode = node.Parent.Parent; // or null if none
Если Вы часто используете его в кодовой базе, я думаю, что это хорошо, поскольку это не слишком трудно понять на первом чтении и уменьшило размер кода – поэтому помогает мне видеть лес от деревьев.
Однако, если только используется 1 или 2 раза, я думаю "в строке", если будет лучше, поскольку я не вижу для размышления о значении, “если” в первый раз я вижу его.
"В строке", если - я имею в виду нормальное, если оператор, который не имеет быть скрытым в отдельном методе.
Кажется достаточно читаемым, хотя это все еще немного неуклюже.
Это походит на идеальную возможность реализовать шаблон несуществующего объекта все же.
Рассмотрите:
public class Foo
{
public Foo(string value) { Value=value; }
public string Value { get; private set; }
private static Foo nullFoo = new Foo("default value");
public static Foo NullFoo { get { return nullFoo; } }
}
Затем имейте getSomeFoo (), возвращают Foo. NullFoo вместо пустого указателя. Это требует небольшой дополнительной мысли, но обычно делает для более хорошего кода.
Обновление в ответ на комментарии:
Скажем, Вы не управляете Foo, можно все еще (часто) делать это (который является больше, как Вы хотели бы реализовать его независимо):
public class NullFoo : Foo
{
private NullFoo() : base("default value") { }
private static NullFoo instance = new NullFoo();
public static Foo Instance { get { return instance; } }
}
Затем возвратите NullFoo. Экземпляр от getSomeFoo (). Если Вы не управляете getSomeFoo () также, у Вас и все же есть опция сделать это:
Console.WriteLine((getSomeFoo() ?? NullFoo.Instance).Value);
Почему не записать нормальную функцию Coalesce, то вы могли бы использовать это так:
coalesce(something, something_else, "default");
Другими словами - Что вам нужны лямбдас?
?Отличный пост! Я обновил ваш код, чтобы поддержать возвращение Nullable, потому что NULLABLE реализован как структура.
public static class Coalesce
{
public static TResult UntilNull<T, TResult>(T obj, Func<T, TResult> func) where TResult : class
{
if (obj != null) return func(obj);
else return null;
}
public static TResult UntilNull<T1, T2, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, TResult> func2) where TResult : class
{
if (obj != null) return UntilNull(func1(obj), func2);
else return null;
}
public static TResult UntilNull<T1, T2, T3, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, TResult> func3) where TResult : class
{
if (obj != null) return UntilNull(func1(obj), func2, func3);
else return null;
}
public static TResult UntilNull<T1, T2, T3, T4, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, T4> func3, Func<T4, TResult> func4) where TResult : class
{
if (obj != null) return UntilNull(func1(obj), func2, func3, func4);
else return null;
}
public static Nullable<TResult> UntilNull<T, TResult>(T obj, Func<T, Nullable<TResult>> func) where TResult : struct
{
if (obj != null) return func(obj);
else return new Nullable<TResult>();
}
public static Nullable<TResult> UntilNull<T1, T2, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, Nullable<TResult>> func2) where TResult : struct
{
if (obj != null) return UntilNull(func1(obj), func2);
else return new Nullable<TResult>();
}
public static Nullable<TResult> UntilNull<T1, T2, T3, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, Nullable<TResult>> func3) where TResult : struct
{
if (obj != null) return UntilNull(func1(obj), func2, func3);
else return new Nullable<TResult>();
}
public static Nullable<TResult> UntilNull<T1, T2, T3, T4, TResult>(T1 obj, Func<T1, T2> func1, Func<T2, T3> func2, Func<T3, T4> func3, Func<T4, Nullable<TResult>> func4) where TResult : struct
{
if (obj != null) return UntilNull(func1(obj), func2, func3, func4);
else return new Nullable<TResult>();
}
}