Правильный способ обновления монго в патче в web api

Я хочу реализовать действие Patch в веб-интерфейсе, рассмотрим коллекцию клиентов в Монго, например:

public string Id{ get; set; }
public string Name{ get; set; }
public string Family{ get; set; }
public string Sex{ get; set; }
public string City{ get; set; }
public string CustomerId{ get; set; }

в моем API я получаю этот объект в качестве ввода. клиент может отредактировать одно или несколько из этих полей, если свойство имеет значение null, это означает, что значение должно оставаться прежним значением. то, что я хочу сделать, это в запросе Монго, я хочу сказать, если свойство имеет значение null, не обновлять, учтите это:

var filter = Builders<Customer>.Filter.Eq(s => s.CustomerId, CustomerId);
var builder = Builders<Customer>.Update.Set(???)//set only not null values
mongo.UpdateOne(filter, builder);

* Кстати, лучшее решение для этого ценится

1 ответ

Решение

Вы могли бы сделать что-то вроде этого.

var filter = Builders<Customer>.Filter
    .Eq(s => s.CustomerId, customer.CustomerId); //perhaps requires an index on CustomerId field
var update = Builders<Customer>.Update
    .Set(p => p.CustomerId, customer.CustomerId);
if (!string.IsNullOrWhiteSpace(customer.City))
    update = update.Set(p => p.City, customer.City);
if (!string.IsNullOrWhiteSpace(customer.Name))
    update = update.Set(p => p.Name, customer.Name);
if (!string.IsNullOrWhiteSpace(customer.Family))
    update = update.Set(p => p.Family, customer.Family);
if (!string.IsNullOrWhiteSpace(customer.Sex))
    update = update.Set(p => p.Sex, customer.Sex);

customers.UpdateOne(filter, update);

Другой подход может рассматривать вашу клиентскую сущность в целом (ориентированные на документы базы данных поощряют этот подход), таким образом, всегда обновляя сущность целиком и избегая детальных обновлений (что более вероятно в случае R-СУБД). В этом случае вы можете написать что-то вроде этого.

var customerFromDb = customers
    .Find(p => p.CustomerId == customer.CustomerId)
    .Single();

if (!string.IsNullOrWhiteSpace(customer.City))
    customerFromDb.City = customer.City;
if (!string.IsNullOrWhiteSpace(customer.Name))
    customerFromDb.Name = customer.Name;
if (!string.IsNullOrWhiteSpace(customer.Family))
    customerFromDb.Family = customer.Family;
if (!string.IsNullOrWhiteSpace(customer.Sex))
    customerFromDb.Sex = customer.Sex;

customers.ReplaceOne(p => p.CustomerId == customer.CustomerId, customerFromDb);

Этот второй подход имеет следующие преимущества и недостатки.

профессионал

  • обновление происходит на уровне домена (возможно, с помощью хорошо подходящих методов), что позволяет применять все правила домена и предотвращать попадание грязных данных в базу данных; таким образом, он более объектно-ориентирован.

Cons

  • этот подход требует двух попаданий в базу данных (один для чтения и один для обновления);
  • если ваша организация велика, сеть должна транспортировать больше данных, чем строго необходимо.

Учитывая, что преждевременная оптимизация является корнем всего зла (или, по крайней мере, большей его части) в программировании ( здесь), в общем, я бы пошел на второй подход, прибегая к первому только в случае очень строгих требований к производительности или низких пропускная способность сети.

Другие вопросы по тегам