实体框架 - 代码优先 - 无法存储列表<String>

 Sunny-阿坚 发布于 2023-02-08 19:23

我写了这样的课:

class Test
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    [Required]
    public List Strings { get; set; }

    public Test()
    {
        Strings = new List
        {
            "test",
            "test2",
            "test3",
            "test4"
        };
    }
}

internal class DataContext : DbContext
{
    public DbSet Tests { get; set; }
}

运行代码后:

var db = new DataContext();
db.Tests.Add(new Test());
db.SaveChanges();

我的数据正在保存但只是保存Id.我没有任何表格,也没有适用于字符串列表的关系.

我究竟做错了什么?我也尝试制作字符串, virtual但它没有改变任何东西.

谢谢您的帮助.

7 个回答
  • 该答案基于@Sasan和@CAD bloke提供的答案。

    仅适用于EF Core 2.1+(不兼容.NET Standard)(Newtonsoft JsonConvert

    builder.Entity<YourEntity>().Property(p => p.Strings)
        .HasConversion(
            v => JsonConvert.SerializeObject(v),
            v => JsonConvert.DeserializeObject<List<string>>(v));
    

    使用EF Core流畅配置,我们List可以对JSON进行序列化/反序列化。

    为什么此代码是您可以争取的一切的完美结合:

    Sasn最初的答案的问题是,如果列表中的字符串包含逗号(或选择作为分隔符的任何字符),它将变成一个大混乱,因为它将单个条目转换为多个条目,但这是最容易阅读和阅读的。最简洁。

    CAD bloke答案的问题在于它丑陋且需要更改模型,这是一种不良的设计实践(请参阅Marcell Toth对Sasan答案的评论)。但这是数据安全的唯一答案。

    2023-02-08 19:24 回答
  • 我知道这是一个老问题,Pawel给出了正确答案,我只想展示一个如何进行字符串处理的代码示例,并避免为基本类型列表添加额外的类.

    public class Test
    {
        public Test()
        {
            _strings = new List<string>
            {
                "test",
                "test2",
                "test3",
                "test4"
            };
        }
    
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
    
        private List<String> _strings { get; set; }
    
        public List<string> Strings
        {
            get { return _strings; }
            set { _strings = value; }
        }
    
        [Required]
        public string StringsAsString
        {
            get { return String.Join(',', _strings); }
            set { _strings = value.Split(',').ToList(); }
        }
    }
    

    2023-02-08 19:25 回答
  • EF Core 2.1+:

    属性:

    public string[] Strings { get; set; }
    

    OnModelCreating:

    modelBuilder.Entity<YourEntity>()
                .Property(e => e.Strings)
                .HasConversion(
                    v => string.Join(',', v),
                    v => v.Split(',', StringSplitOptions.RemoveEmptyEntries));
    

    2023-02-08 19:25 回答
  • JSON.NET来救援.

    您将其序列化为JSON以在数据库中持久化并对其进行反序列化以重构.NET集合.这似乎比我预期的Entity Framework 6和SQLite表现更好.我知道你要求,List<string>但这里有一个更复杂的收藏品的例子.

    我标记了持久性属性,[Obsolete]因此在正常的编码过程中对我来说非常明显"这不是你正在寻找的属性"."真实"属性被标记为,[NotMapped]因此实体框架忽略它.

    (不相关的切线):你可以用更复杂的类型做同样的事情,但你需要问自己,你是否只是为自己查询对象的属性太难了?(是的,在我的情况下).

    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);
        }
    }
    

    2023-02-08 19:25 回答
  • 当然Pawel给出了正确的答案.但我在这篇文章中发现,自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"
            };
        }
    }
    

    2023-02-08 19:25 回答
  • 实体框架不支持基本类型的集合.您可以创建实体(将保存到不同的表)或执行一些字符串处理以将列表保存为字符串,并在实体实现后填充列表.

    2023-02-08 19:25 回答
  • 只是为了简化 -

    实体框架不支持原语.您可以创建一个类来包装它,也可以添加另一个属性来将列表格式化为字符串:

    public ICollection<string> List { get; set; }
    public string ListString
    {
        get { return string.Join(",", List); }
        set { List = value.Split(',').ToList(); }
    }
    

    2023-02-08 19:25 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有