База данных EF Core в памяти Добавление повторяющихся объектовC#

Место общения программистов C#
Ответить
Anonymous
 База данных EF Core в памяти Добавление повторяющихся объектов

Сообщение Anonymous »

Во время модульного тестирования класса My PrivateChatRoomRepository я обнаружил, что иногда, когда я добавляю одно сообщение, дубликат этого сообщения сохраняется в базе данных, хотя при вызове метода обновления мой объект имеет только единственное сообщение в отсортированном наборе. >
Класс гарантированного сообщения переопределяет Equals() и GetHashCode() на основе уникального идентификатора.
Использовал AsNoTracking() в своем методе GetByIdAsync().
Проверил, что dbContext обновлен каждый тест путем реализации IDisposable и удаления контекста после каждого теста.
using VirtualOffice.Domain.DomainEvents.AbstractChatRoomEvents;
using VirtualOffice.Domain.Entities;
using VirtualOffice.Domain.Exceptions.ChatRoom;
using VirtualOffice.Domain.ValueObjects.AbstractChatRoom;
using VirtualOffice.Domain.ValueObjects.ApplicationUser;

namespace VirtualOffice.Domain.Abstractions
{
public abstract class AbstractChatRoom : AggregateRoot
{
public HashSet _Participants { get; private set; }

public SortedSet _Messages { get; private set; }

protected AbstractChatRoom(ChatRoomId id, HashSet participants, SortedSet messages)
{
if (messages is null)
throw new ArgumentNullException($"{nameof(messages)} cannot be null");
else if (participants is null)
throw new ArgumentNullException($"{nameof(participants)} cannot be null");
else if (participants.Count < 2)
throw new InvalidChatRoomParticipantsException();
Id = id;
_Participants = participants;
_Messages = messages;
}

protected AbstractChatRoom()
{ }

public void SendMessage(ApplicationUser sender, string content)
{
if (!_Participants.Contains(sender))
throw new UserIsNotAParticipantOfThisChatException(sender.Id);
Message message = new Message(Guid.NewGuid(), sender, content);
_Messages.Add(message);

AddEvent(new ChatRoomMessageSent(this, message));
}

public ApplicationUser GetParticipantById(ApplicationUserId id)
=> _Participants.FirstOrDefault(u => u.Id == id) ?? throw new ChatRoomParticipantNotFoundException(id.ToString());
}
}

using VirtualOffice.Domain.Abstractions;
using VirtualOffice.Domain.Exceptions.ChatRoom;
using VirtualOffice.Domain.ValueObjects.AbstractChatRoom;

namespace VirtualOffice.Domain.Entities
{
public class PrivateChatRoom : AbstractChatRoom
{
public PrivateChatRoom(ChatRoomId id, HashSet participants, SortedSet messages) : base(id, participants, messages)
{
if (participants.Count != 2)
throw new InvalidPrivateRoomParticipantsException();
}

private PrivateChatRoom()
{ }
}
}

using System.Xml.Linq;
using VirtualOffice.Domain.ValueObjects.Message;
using VirtualOffice.Shared;

namespace VirtualOffice.Domain.Entities
{
public class Message : IEquatable, IComparable
{
private readonly IDateTimeProvider _dateTimeProvider;
private readonly ApplicationUser _sender;
private readonly MessageContent _content;

public MessageId Id { get; }
public ApplicationUser Sender => _sender;
public DateTime SendDate => _dateTimeProvider.UtcNow();
public MessageContent Content => _content;

public Message(MessageId id, ApplicationUser sender, MessageContent content)
{
Id = id;
_sender = sender;
_content = content;
_dateTimeProvider = new DateTimeProvider();
}

protected Message(MessageId id, ApplicationUser sender, MessageContent content, IDateTimeProvider dateTimeProvider)
{
Id = id;
_sender = sender;
_content = content;
_dateTimeProvider = dateTimeProvider;
}

private Message()
{ }

public int CompareTo(Message? other)
{
if (other == null)
throw new ArgumentNullException();
return other.SendDate.CompareTo(this.SendDate);
}

public bool Equals(Message other)
{
if (other == null) return false;
return Id.Equals(other.Id);
}

public override bool Equals(object obj)
{
return Equals(obj as Message);
}

public override int GetHashCode()
{
return Id.GetHashCode();
}
}
}

public async Task UpdateAsync(PrivateChatRoom chatRoom)
{
_dbContext.PrivateChatRooms.Update(chatRoom);
await _dbContext.SaveChangesAsync();
}

public async Task
GetByIdAsync(ChatRoomId guid)
=> await _dbContext.PrivateChatRooms
.Include(pcr => pcr._Participants)
.Include(pcr => pcr._Messages)
.FirstOrDefaultAsync(pcr => pcr.Id == guid) ?? throw new PrivateChatRoomNotFoundException(guid);

[Fact]
public async Task UpdateAsync_ExistingPrivateChatRoom_ShouldContainSingleMessage()
{
// Arrange
var pcr = await _repository.GetByIdAsync(_pcrGuid1);
// Act
pcr.SendMessage(_user1, "NewMessage");
await _repository.UpdateAsync(pcr);
// Assert
var result = _dbContext.PrivateChatRooms.First(x => x.Id.Value == _pcrGuid1);
Assert.Single(result._Messages);
}

Настройка базы данных памяти в конструкторе
// setup in memory db
var options = new DbContextOptionsBuilder()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;

_dbContext = new WriteDbContext(options);
_repository = new PrivateChatRoomRepository(_dbContext);
_dbContext.PrivateChatRooms.AddRange(_data[0], _data[1]);
_dbContext.SaveChanges();


Подробнее здесь: https://stackoverflow.com/questions/790 ... e-entities
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»