【问题标题】:How do I update my database without having to wipe it each time I save data to it如何更新我的数据库而不必在每次将数据保存到它时擦除它
【发布时间】:2021-01-25 09:35:37
【问题描述】:

我目前构建了一个 Visual Studio C# 项目,它通过实体框架将 API 数据保存到数据库中。每次我运行项目时,数据库中的表都会被擦除,然后再次重新添加数据。这是为了停止重复。但是,我想知道是否有替代路线我不必擦除数据但我可以添加不存在的新数据?

这是我项目中的代码。从我的主类中使用 RestSharp 获取 API 数据的方法开始,反序列化为 JSON 格式,然后保存到我的数据库。

public static void getAllRequestData()
{
    var client = new RestClient("[My API URL]");
    var request = new RestRequest();
    var response = client.Execute(request);

    if (response.StatusCode == System.Net.HttpStatusCode.OK)
    {
        string rawResponse = response.Content;
        AllRequests.Rootobject result = JsonConvert.DeserializeObject<AllRequests.Rootobject>(rawResponse);

        using (var db = new TransitionContext())
        {
            db.RequestDetails.RemoveRange(db.RequestDetails); //Wipes Data
            db.RequestDetails.AddRange(result.Operation.Details); //Adds Data
            db.SaveChanges(); 
        } //Utilising EF to save data to the DB
    }
} //Method that calls and stores API data

这是下面的实体框架类,你可以看到它只支持一个表(数据集)。

public class TransitionContext : DbContext
{
    private const string connectionString = @"[My Server]";

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(connectionString);
    }

    public DbSet<AllRequests.Detail> RequestDetails { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AllRequests.Detail>().HasKey(r => r.Id);
    }
}

这里是 DTO 类,它临时保存数据,用于构建适合 API 数据的类。

public class AllRequests
    {
        public class Rootobject
        {
            public Operation Operation { get; set; }
        }

        public class Operation
        {
            public Result Result { get; set; }
            public Detail[] Details { get; set; }
        }

        public class Result
        {
            public string Message { get; set; }
            public string Status { get; set; }
        }

        public class Detail
        {
            [Key]
            public int Id { get; set; }
            public string Requester { get; set; }
            public string WorkOrderId { get; set; }
            public string AccountName { get; set; }
            public string CreatedBy { get; set; }
            public string Subject { get; set; }
            public string Technician { get; set; }
            public string IsOverDue { get; set; }
            public long DueByTime { get; set; }
            public string Priority { get; set; }
            public long CreatedTime { get; set; }
            public string IgnoreRequest { get; set; }
            public string Status { get; set; }
        }
    }

这是生成的表(不相关的数据被屏蔽)。

为了让 Entity Framework 正常工作,我必须创建一个 ID。此 ID 不包含任何 API 数据,它只是从 1 开始到有多少行。但是,WorkOrderId 是每一行的唯一 ID。我怎样才能让这个项目扫描表中的 WorkOrderId,并且只在没有 WorkOrderId 的地方添加新数据?

因为理想情况下,我希望每 5-10 分钟运行一次这个项目,以保持表格不断更新,但是,目前我觉得擦桌子并不是理想的方式,而且是一个漫长的过程。如果我可以实现这个过程,我会更喜欢它。任何帮助或指示将不胜感激。

【问题讨论】:

  • 那么应该如何处理已插入数据库但在新记录批次中不存在的记录?
  • 在这种情况下永远不会发生这种情况,无论如何,所有被拉取的记录都将保留在那里。

标签: c# sql-server entity-framework restsharp dto


【解决方案1】:

简答 - 使用唯一约束并配置 EF。

长答案 - 您应该更加熟悉数据库和实体框架。 数据库应确保您没有重复。

主键(这里是你的 ID)比你想象的重要得多。


A table can have only one primary key, which may consist of single or multiple fields. When multiple fields are used as a primary key, they are called a composite key.

If a table has a primary key defined on any field(s), then you cannot have two records having the same value of that field(s).

(https://www.tutorialspoint.com/sql/sql-primary-key.htm)

此外,在某些数据库(例如 SQL Server)中,您可以在多个列上构建主键。

另一个想法是正确配置实体框架。基本上,您在 OnModelCreating 中执行此操作。

你可以在这里说一列应该是唯一的,例如:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>()
        .HasIndex(u => u.Email)
        .IsUnique();
}

您可以在此处阅读有关索引的更多信息:https://en.wikipedia.org/wiki/Database_index 和此处:How does database indexing work?

看来您应该将字段 WorkOrderId 设为主键并删除 Id 字段。我认为您还应该阅读有关外键的更多信息:https://www.w3schools.com/sql/sql_foreignkey.asp

【讨论】:

  • 感谢您的回复,虽然我对 Entity Framework 很陌生,但我确实知道 PK 和 FK 的工作原理。我接受了您的建议,我已经摆脱了 Id 键,而是将 WorkOrderId 作为我的 PK。我已经在 Entity Framework 中重新构建了它并填充了表格。现在唯一的问题是,当我再次运行它时,它说“无法插入重复的主键”,所以我不能再用这个 API 更新表了?
  • 因为理想情况下,我希望能够每 10 分钟运行一次这个程序,所以它会添加新数据,我发现了如何通过先擦除数据然后一遍又一遍地重新添加来做到这一点.但我发现擦除数据并不是最好的方法。作为您建议的一部分,我将阅读有关数据库索引的信息,再次感谢您的帮助 Adam 我很感激。
  • 您似乎一直在尝试添加相同的记录。不要那样做。
  • 我知道它正在这样做,但我想找到一个解决方案来解决如何只添加不存在的记录,如果这有意义的话?基本上我只想在每次启动应用程序时更新我的​​表。
  • 我不明白你的问题。您从哪里将记录放入数据库?
猜你喜欢
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
  • 2014-03-30
  • 2023-03-13
  • 1970-01-01
  • 2017-09-29
相关资源
最近更新 更多