Как я могу использовать последний драйвер MongoDB C# для удаления элемента во вложенном массиве объектов сложного массива на основе нескольких условий? - PullRequest
0 голосов
/ 04 апреля 2020

Общая цель состоит в том, чтобы иметь возможность выполнить поиск пищи на основе идентификатора пользователя и идентификатора еды. Если этот элемент найден, я хочу иметь возможность удалить только весь элемент, который совпадает как с идентификатором пользователя, так и с едой.

В настоящее время, после отправки объекта запроса через почтальона в запросе на публикацию, я попытался написать вариация запросов с использованием C# для создания объекта компоновщика, а затем фильтрация для поиска указанного объекта массива c и, наконец, удаление объекта массива, если есть совпадения как для ИД пользователя, так и для еды, Первоначально у меня возникла проблема, когда не удалялся весь элемент, а только элемент целочисленного массива, который вложен в элемент (не удалялся, а возвращался к нулевым значениям). Однако теперь проблема в том, что весь элемент массива вообще не удаляется, и я получаю следующую ошибку. BsonArraySerializer Ошибка из Visual Studio

Может кто-нибудь помочь мне решить эту проблему?

Вот пример объекта, который я отправляю через почтальона, который я пытаюсь для удаления: Пример POST-запроса почтальона с данными тела

Вот пример изображения данных, которые я пытаюсь удалить: Пример изображения Json Array Elemet I ' m пытается удалить

Вам понадобится компас или атлас MongoDb. NET Core 3.1, MongoDB C# Драйвер 2.0, Почтальон и. NET Core 3.1 WebApi Project / Solution для решения этой проблемы.

Ниже приведен код, необходимый для репликации проблемы:

Startup.cs

Добавьте эту строку кода в метод конфигурации этого файла

services.AddScoped<IMealsRepository, MealsRepository>();

Добавьте эту строку в метод ConfigureServices

services.AddSingleton(sp =>
            sp.GetRequiredService<IOptions<DatabaseSettings>>().Value);

appSettings. json

Добавьте эти строки кода в этот файл

 "DatabaseSettings": {

    "ConnectionString": "your connection string to MongoDb"

}

База данных Setti ngs.cs

    public class DatabaseSettings
    {
        public string ConnectionString { get; set; } 
    }

MealPlanModel.cs:

using MongoDB.Bson;

using MongoDB.Bson.Serialization.Attributes;

public class MealPlanModel
{

    #region MealPlanModel fields
    [BsonElement("userid")]
    public int? UserId { get; set; }

    [BsonElement("mealid")]
    public int? MealId { get; set; }

    [BsonElement("mealname")]
    public string MealName { get; set; }

    [BsonElement("mealimage")]
    public string MealImage { get; set; }

    [BsonElement("foods")]
    public FoodModel[] Foods { get; set; }

    [BsonElement("totalcalories")]
    public double TotalCalories { get; set; }

    [BsonElement("totalprotein")]
    public double TotalProtein { get; set; }

    [BsonElement("totalcarbs")]
    public double TotalCarbs { get; set; }


    [BsonElement("totalfat")]
    public double TotalFat { get; set; }

    [BsonElement("totalsugar")]
    public double TotalSugar { get; set; }

    [BsonElement("totalfiber")]
    public double TotalFiber { get;  set; }
    #endregion

    #region MealPlanModel ctor
    public MealPlanModel()
    {

    }

    public MealPlanModel(int userid, int mealid)
    {
        UserId = userid;
        MealId = mealid;
    }
}

MealPlanDto.cs

using MongoDB.Bson;

using MongoDB.Bson.Serialization.Attributes;

using System.Collections.Generic;

public class MealPlanDto

{

    [BsonId]
    public ObjectId Id { get; set; }

    [BsonElement("meals")]
    public List<MealPlanModel> MealPlans { get; set; }
}

**MealsController.cs:**


using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Security.Claims;

using System.Threading.Tasks;

using AutoMapper;

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using Newtonsoft.Json;

[Route("api/[controller]")]

[ApiController]

public class MealsController : ControllerBase

{


    private readonly IMealsRepository _repo;

    private readonly IMapper _mapper;

    public MealsController(IMealsRepository repo, IMapper mapper)
    {
        _repo = repo;

        _mapper = mapper;

    } 


    [HttpGet, Route("CheckConnection")]

    public async Task<IActionResult> CheckConnection()

    {

        var result = await _repo.CheckConnection();

        if (result == null || result.Count <= 0)

            return BadRequest("Failed to connect to database.");

        return Ok("Database connection was successful");

    }

    [HttpPost("deletecustommeal")]

    public async Task<IActionResult> DeleteCustomMealPlan(int id)

    {

      var requestBody = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
      var mealPlanToDelete = JsonConvert.DeserializeObject<MealPlanModel>(requestBody);
      MealPlanDto deleteMealPlan = new MealPlanDto();
      deleteMealPlan.MealPlans = new List<MealPlanModel>();
      deleteMealPlan.MealPlans.Add(mealPlanToDelete);
      var result = await _repo.DeleteCustomMealPlanById(deleteMealPlan);
      if (!result)
         return BadRequest("Failed to delete meal");
      return Ok("Successfully deleted meal plan");
    }

}

MealsRepository.cs

using Microsoft.Extensions.Configuration;

using MongoDB.Bson;

using MongoDB.Driver;

using System;

using System.Collections.Generic;

using System.Threading.Tasks;

public class MealsRepository : IMealsRepository

{

    private readonly MongoClient _client;

    private readonly IMongoDatabase _database;

    private readonly IMongoCollection<MealPlanDto> _userMealsCollection;

    public MealsRepository(IConfiguration configuration)
    {
        _client = new 
          MongoClient(configuration.GetSection("DatabaseSettings").GetSection("ConnectionString").Value);
        _database = _client.GetDatabase("MealsDb");
        _userMealsCollection = _database.GetCollection<MealPlanDto>("meal");
    }

    public async Task<List<BsonDocument>> CheckConnection()
    {
        List<BsonDocument> list = await _database.ListCollections().ToListAsync();
        var populatedList = (list != null && list.Count > 0) ? list : null;
        return populatedList;
    }

    public async Task<bool> DeleteCustomMealPlanById(MealPlanDto mealPlanToDelete)

    {
        var builder = Builders<MealPlanDto>.Filter;
        var filter = builder.Eq(x => x.MealPlans[0].UserId, mealPlanToDelete.MealPlans[0].UserId);

        var update = Builders<MealPlanDto>.Update.PullFilter(
            p => (IEnumerable<MealPlanModel>)p.MealPlans[0],
            f => f.MealId.Value == mealPlanToDelete.MealPlans[0].MealId);

        try
        {
            await _userMealsCollection.UpdateOneAsync(filter, update);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Failed to delete meal plan. {ex} occured.");
            return false;
        }
    }

}

1 Ответ

0 голосов
/ 16 апреля 2020

Спасибо за все, что пытались найти ответ на мой вопрос выше, но на самом деле я нашел простое решение

Я просто заменил вышеуказанный метод в файле Repository.cs на следующий, и он работает как очарование

public bool DeleteCustomMealPlanForUserById(MealPlanModel mealPlanToDelete)
    {
        var result = _customUserMealsCollection.DeleteOne(p => p.MealPlans[0].UserId == mealPlanToDelete.UserId
            && p.MealPlans[0].MealId == mealPlanToDelete.MealId);

        return result.DeletedCount != 0;
    }
...