#c# #.net-core #entity-framework-core #blazor
#c# #.net-ядро #сущность-основа-ядро #блейзор
Вопрос:
Я работаю над небольшим приложением для организации бронирования отелей в Entity Framework Core. Мне нужно добавить информацию о количестве и типе кроватей в каждой комнате. Я подумал и решил, что список перечислений будет лучше, чем хранить его в отдельной таблице. Но я не знаю, как этого добиться
public enum Bed
{
Single = 1,
Double = 2,
}
public class Room : IEntity
{
[Key]
public int Id { get; set; }
public string RoomIdentifier { get; set; }
public ICollection<Bed> Beds { get; set; }
public int Floor { get; set; }
public double Price { get; set; }
public bool IsFree { get; set; }
public bool IsOutOfService { get; set; }
public bool ShouldBeCleaned { get; set; }
public ICollection<RoomReservation> RoomReservations { get; set; }
}
Возможно ли это сделать? Я также думал сохранить его в виде строки, например (1,2,1,2), а затем проанализировать его, чтобы получить количество и тип кроватей в комнате. Большое спасибо за помощь!
Комментарии:
1. По умолчанию список перечислений будет храниться в отдельной таблице. таким образом, строка идентификаторов, проанализированная обратно в список, будет пользовательским сериализатором
2. Перечисления хранятся в базе данных в виде целых чисел. Преобразователи значений используются для преобразования между типом перечисления и его числовым эквивалентом. См. docs.microsoft.com/en-us/ef/core/modeling/value-conversions
3. @RobertHarvey Этого было бы достаточно, если бы у меня было одно значение enum, но в моем случае у меня есть список перечислений для каждого объекта room, я не знаю, сработает ли это.
4. Я не понимаю, как список перечислений будет отличаться от списка любого другого объекта.
5. Не используя отдельную таблицу, вы не получаете ничего, кроме проблем — нестандартное обнаружение изменений, невозможность выполнения критериев запроса на стороне сервера для такого «столбца» и т. Д. Хранение значений в строке, разделенной запятыми, ничем не лучше, чем хранение дат / чисел в строке вместо собственного типа данных. В настоящее время таблицы базы данных (особенно когда они управляются с помощью миграции кода ORM) бесплатны (в основном бесплатно), просто используйте их и не тратьте свое время. Я почти уверен, что следующий вопрос, который вы отправите через несколько дней после этого, будет «как найти комнаты с определенным количеством и типом кроватей, используя LINQ и EF Core», без хорошего ответа
Ответ №1:
Вот пример с составленными именами объектов, надеюсь, это поможет.
В OnModelCreating:
modelBuilder.Entity<Room>()
.Property(e => e.BedList)
.HasConversion(
v => string.Join(',', v),
v => v.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<Bed>())
.Metadata.SetValueComparer(valueComparer);
Вам нужно будет создать свой собственный пример valuecomparer ниже
для списка:
var valueComparer = new ValueComparer<ICollection<string>>(
(c1, c2) => c1.SequenceEqual(c2),
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
c => (ICollection<string>)c.ToHashSet());
Комментарии:
1. Зачем мне нужно иметь
ValueComparer
? Здесь все работает нормально и без него.2. Отслеживание изменений @RogerioSchmitt может определять изменение столбца и выполнять запись, когда это не требуется, без средства сравнения значений. но, честно говоря, я не тестировал без.
Ответ №2:
Я неправильно понял вопрос… если вы пытаетесь сохранить список, разделенный запятыми, в одном поле, следуйте примеру Ричарда … или обработайте его вручную в своей логике сопоставления, если она у вас есть.
Приведенный ниже ответ будет дан только в том случае, если вы пытаетесь использовать перечисление вместо таблицы, а не в том случае, если вы пытаетесь поместить несколько значений перечисления в один столбец.
Есть хороший пакет C #, который называется SmartEnum
Ardalis Steve Smith. Ссылка на GitHub
Это позволит вам иметь строго типизированное перечисление, но вы можете сохранить его в базе данных в виде строки или целого числа или как вам угодно.
Вот пример:
public sealed class Bed : SmartEnum<TestEnum>
{
// static instances of the SmartEnum Bed represents the enumerations
public static readonly Bed Single = new Bed(name: "Single", value: 1, isPremium: false);
public static readonly Bed Double = new Bed(name: "Double", value: 2, isPremium: true);
// example additional property of each enumeration
public bool IsPremium = false;
private Bed(string name, int value, bool isPremium) : base(name, value)
{
IsPremium = isPremium;
}
}
В приведенном выше примере перечисление подкрепляется int
значением. Вы можете подкрепить его строкой, используя : SmartEnum<TestEnum, string>
. Он поддерживает неявные приведения и т. Д., Хорошо работает с EF, и вы сможете «перечислять» перечисления по мере необходимости.
Комментарии:
1. Хм. Dapper не требует ничего из этого; вы просто объявляете свое свойство в DTO как тип перечисления, и Dapper автоматически выполняет правильные действия (поле базы данных — an
int
).2. @RobertHarvey о, конечно, это альтернатива — вместо этого решает проблему на уровне домена.
3. Да, я думал, что сохранение этих значений в виде строковых значений было бы лучшим, но другие предложения также очень ценятся
4. Ядро EF также делает это автоматически и поддерживает как хранение (так и запрос) значений перечислений в виде int или string в базе данных, поэтому никаких дополнительных пакетов не требуется.
5. @IvanStoev я в курсе, как я уже говорил ранее… это решает проблему на уровне домена, и у этого есть свои преимущества.