【问题标题】:Entity Framework not saving all the information into database实体框架未将所有信息保存到数据库中
【发布时间】:2020-01-21 12:22:43
【问题描述】:

我遇到了一个问题,我尝试了一些解决方案来解决这个问题,但我无法解决。 基本上,我有一个方法,我从 ajax post 接收一个字符串和一个序列化 Map 作为参数。 与此相关的一切都运行良好,除了当我有相同的 FileId 和不同的 UseCaseId 时,因为那时只保存一个信息,而不是两个。

**UseCaseId 和 FileId ** 是来自其他表的外键。

关系:

modelBuilder.Entity<Content>()
        .HasIndex(ct => ct.FileId)
        .IsUnique(false);
    modelBuilder.Entity<Content>()
        .HasIndex(ct => ct.UseCaseId)
        .IsUnique(false);

    modelBuilder.Entity<Content>()
        .HasKey(cn => cn.ContentId);
    modelBuilder.Entity<Content>()
        .HasOne(cn => cn.File)
        .WithOne()
        .OnDelete(DeleteBehavior.Cascade);
    modelBuilder.Entity<Content>()
        .HasOne(cn => cn.UseCase)
        .WithOne()
        .OnDelete(DeleteBehavior.Cascade);

在以下示例中,需要保存两个完全相同的元素,只是 UseCase 不同,但只有最后一个元素保存在数据库中。

Contents variable

Database - Result

收到的参数:

Parameter Received

这是出现问题的代码:

[HttpPost]
public JsonResult Create([FromBody] ContentJson data)
{
    List<Content> contents = new List<Content>();
    var contentName = string.Empty;
    var array = data.content;
    int order;

    for (int i = 0; i < array.Count; i++)
    {
        var files = JsonConvert.DeserializeObject<string[]>(array[i][1].ToString());

        if (files == null || files.Length == 0)
            continue;

        contentName = array[i][0].ToString();
        order = 1;

        foreach(var fileName in files)
        {
            Content content = new Content();    
            content.Order = order;
            content.UseCaseId = long.Parse(contentName);
            content.FileId = unitOfWork.FileRepository.Get(f => f.FileName.Equals(fileName)).First().FileId;
            contents.Add(content);
            order++;
        }
    }

    unitOfWork.ContentRepository.AddRange(contents);
    unitOfWork.Save();

    return Json(Ok());
}
  • ContentId 是自动生成的。
  • EntityFramework 和 Dotnet 的最新版本
  • 我已经尝试在每次迭代中保存。
  • 试图实现 Equals 和 HashCode,

    public void Save()
    {
        context.SaveChanges();
    }
    
    private bool disposed = false;
    
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        disposed = true;
    }
    
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    
    
    
    public Repository<Content> ContentRepository
    {
        get
        {
            if(contentRepository == null)
            {
                contentRepository = new Repository<Content>(context);
            }
            return contentRepository;
        }
    }
    

有人可以帮帮我吗?我被这个问题困住了。

【问题讨论】:

  • 分享unitOfWork.Save();代码。
  • 我也添加了 UnitOfWork
  • @JoseAguiar DbContext 一个 UoW。 DbSet 一个存储库。添加“通用”存储库只会通过尝试在更高级别的抽象之上强制使用低级别概念来引入问题。请注意您在此处发布的那些代码,甚至是 Dispose 实现,只不过是委托给上下文而已。
  • EF Core 将多个项目保存到数据库没有问题。这里发布的代码虽然使用了其他东西,一些 Repository 类的 AddRangeAdd 方法丢失了。
  • 或者可能是 数据输入 错误 - 代码采用强类型对象,将其转换为字符串,然后尝试将其解析为 JSON。这仅在原始对象是简单字符串时才有效。那么为什么不按原样使用呢?这个字符串可以包含重复项吗?还是只有一个项目?

标签: .net entity-framework asp.net-core .net-core entity-framework-core


【解决方案1】:

您的 FK 配置有冲突。

IsUnique(false)这里

modelBuilder.Entity<Content>()
    .HasIndex(ct => ct.FileId)
    .IsUnique(false);

modelBuilder.Entity<Content>()
    .HasIndex(ct => ct.UseCaseId)
    .IsUnique(false);

暗示 FK 不是唯一的,但这里是 WithOne()

modelBuilder.Entity<Content>()
    .HasOne(cn => cn.File)
    .WithOne()
    .OnDelete(DeleteBehavior.Cascade);

modelBuilder.Entity<Content>()
    .HasOne(cn => cn.UseCase)
    .WithOne()
    .OnDelete(DeleteBehavior.Cascade);

暗示它们是唯一的(关系数据库中一对多和一对一的 FK 关系之间的唯一区别是后面的 FK 由唯一的约束/索引支持)。这优先于非唯一索引映射并导致问题。

由于您希望它们不唯一,因此您必须通过在两个地方替换 WithOne() 来将关系更改为一对多(或多对一,具体取决于您正在查看的哪一方) WithMany().

执行此操作后,您可以删除这两个 HasIndex 配置,因为它们将由 EF Core 约定自动为您创建。事实上,它们也可以使用您的流利配置创建,但是是独一无二的。可能这就是您试图使用这些 HasIndex 语句修复的问题,但这只是错误的地方,您应该修复导致它的原因。

【讨论】:

  • 解决了问题!非常感谢你。我刚刚在这两种情况下将“With One”行更改为“With Many”,删除了“有索引”部分,一切正常!再次非常感谢!
【解决方案2】:

使用 fileName.contentName 代替 contentName
即 content.UseCaseId = long.Parse(fileName.contentName); 同样适用于 fileId

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多