Во время модульного тестирования класса 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
База данных EF Core в памяти Добавление повторяющихся объектов ⇐ C#
Место общения программистов C#
-
Anonymous
1727255893
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();
Подробнее здесь: [url]https://stackoverflow.com/questions/79021999/ef-core-in-memory-database-adding-duplicate-entities[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия