Как хранить массивы строк с помощью Entity Framework без создания новой таблицы? [Дубликат]

Если во время проверки не появляется ошибка MySQL, убедитесь, что вы правильно создали таблицу базы данных. Это случилось со мной. Ищите любые нежелательные запятые или цитаты.

50
задан Uwe Keim 14 November 2015 в 12:01
поделиться

5 ответов

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

104
ответ дан Pawel 25 August 2018 в 19:32
поделиться

Просто для упрощения -

Структура Entity не поддерживает примитивы. Вы либо создаете класс для его переноса, либо добавляете другое свойство для форматирования списка в виде строки:

public ICollection<string> List { get; set; }
public string ListString
{
    get { return string.Join(",", List); }
    set { List = value.Split(',').ToList(); }
}
9
ответ дан Adam Tal 25 August 2018 в 19:32
поделиться

JSON.NET для спасения.

Сериализуйте его в JSON для сохранения в базе данных и Deserialize для восстановления коллекции .NET. Кажется, что это работает лучше, чем я ожидал от него с Entity Framework 6 & amp; SQLite. Я знаю, что вы попросили List<string>, но вот пример еще более сложной коллекции, которая работает очень хорошо.

Я отметил сохраненное свойство с помощью [Obsolete], поэтому было бы очень очевидно, что «это не является тем свойством, которое вы ищете "в процессе обычной кодировки. Свойство «real» помечено значком [NotMapped], поэтому инфраструктура Entity игнорирует его.

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

using Newtonsoft.Json;
....
[NotMapped]
public Dictionary<string, string> MetaData { get; set; } = new Dictionary<string, string>();

/// <summary> <see cref="MetaData"/> for database persistence. </summary>
[Obsolete("Only for Persistence by EntityFramework")]
public string MetaDataJsonForDb
{
    get
    {
        return MetaData == null || !MetaData.Any()
                   ? null
                   : JsonConvert.SerializeObject(MetaData);
    }

    set
    {
        if (string.IsNullOrWhiteSpace(value))
           MetaData.Clear();
        else
           MetaData = JsonConvert.DeserializeObject<Dictionary<string, string>>(value);
    }
}
18
ответ дан CAD bloke 25 August 2018 в 19:32
поделиться

Конечно Павел дал правильный ответ . Но я нашел в этом сообщении , что с EF 6+ можно сохранить частные свойства. Поэтому я бы предпочел этот код, потому что вы не можете сохранить строки неправильно.

public class Test
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Column]
    [Required]
    private String StringsAsStrings { get; set; }

    public List<String> Strings
    {
        get { return StringsAsStrings.Split(',').ToList(); }
        set
        {
            StringsAsStrings = String.Join(",", value);
        }
    }
    public Test()
    {
        Strings = new List<string>
        {
            "test",
            "test2",
            "test3",
            "test4"
        };
    }
}
29
ответ дан Community 25 August 2018 в 19:32
поделиться

Вы можете использовать этот контейнер ScalarCollection, который ограничивает массив и предоставляет некоторые параметры манипуляции ( Gist ):

Использование:

public class Person
{
    public int Id { get; set; }
    //will be stored in database as single string.
    public SaclarStringCollection Phones { get; set; } = new ScalarStringCollection();
}

Код:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

namespace System.Collections.Specialized
{
#if NET462
  [ComplexType]
#endif
  public abstract class ScalarCollectionBase<T> :
#if NET462
    Collection<T>,
#else
    ObservableCollection<T>
#endif
  {
    public virtual string Separator { get; } = "\n";
    public virtual string ReplacementChar { get; } = " ";
    public ScalarCollectionBase(params T[] values)
    {
      if (values != null)
        foreach (var item in Items)
          Items.Add(item);
    }

#if NET462
    [Browsable(false)]
#endif
    [EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("Not to be used directly by user, use Items property instead.")]
    public string Data
    {
      get
      {
        var data = Items.Select(item => Serialize(item)
          .Replace(Separator, ReplacementChar.ToString()));
        return string.Join(Separator, data.Where(s => s?.Length > 0));
      }
      set
      {
        Items.Clear();
        if (string.IsNullOrWhiteSpace(value))
          return;

        foreach (var item in value
            .Split(new[] { Separator }, 
              StringSplitOptions.RemoveEmptyEntries).Select(item => Deserialize(item)))
          Items.Add(item);
      }
    }

    public void AddRange(params T[] items)
    {
      if (items != null)
        foreach (var item in items)
          Add(item);
    }

    protected abstract string Serialize(T item);
    protected abstract T Deserialize(string item);
  }

  public class ScalarStringCollection : ScalarCollectionBase<string>
  {
    protected override string Deserialize(string item) => item;
    protected override string Serialize(string item) => item;
  }

  public class ScalarCollection<T> : ScalarCollectionBase<T>
    where T : IConvertible
  {
    protected override T Deserialize(string item) =>
      (T)Convert.ChangeType(item, typeof(T));
    protected override string Serialize(T item) => Convert.ToString(item);
  }
}
2
ответ дан Shimmy 25 August 2018 в 19:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: