【问题标题】:Azure App Services (Mobile App) Violation of PRIMARY KEY constraintAzure 应用服务(移动应用)违反 PRIMARY KEY 约束
【发布时间】:2016-05-25 14:08:20
【问题描述】:

我正在使用 Azure 应用程序服务(移动应用程序)来开发一个使用 SQLite 的离线同步功能的应用程序。 我的数据对象模型是:

public class Customer : EntityData
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    //…
    public DateTime DateCreated { get; set; }
    public DateTime DateModified { get; set; }
    public virtual IList<Card> Cards { get; set; }
}
public class Card : EntityData
{
    public bool IsDisabled { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime LastUsedDate { get; set; }
}

我的控制器代码是:

    // GET tables/Customer
    public IQueryable<Customer> GetAllCustomers()
    {
        return Query();
    }

    // GET tables/Customer/48D68C86-6EA6-4C25-AA33-223FC9A27959
    public SingleResult<Customer> GetCustomer(string id)
    {
        return Lookup(id);
    }

    // PATCH tables/Customers/48D68C86-6EA6-4C25-AA33-223FC9A27959
    public Task<Customer> PatchCustomer(string id, Delta<Customer> patch)
    {
        return UpdateAsync(id, patch);
    }

    // POST tables/Customer
    public async Task<IHttpActionResult> PostCustomer(Customer item)
    {
        Customer current = await InsertAsync(item);
        return CreatedAtRoute("Tables", new { id = current.Id }, current);
    }

    // DELETE tables/Customer/48D68C86-6EA6-4C25-AA33-223FC9A27959
    public Task DeleteCustomer(string id)
    {
        return DeleteAsync(id);
    }

我不太确定这在幕后是如何映射的,但我从我的客户那里打来电话:

    await App.MobileService.SyncContext.PushAsync();
    await customerTable.PullAsync("customers", customerTable.CreateQuery());

当我执行数据的初始同步以插入客户时,一切正常,但是,当我尝试更新其中任何一个时,我收到一个错误“操作因冲突而失败:'违反 PRIMARY KEY 约束'PK_dbo 。牌'。无法在对象“dbo.Cards”中插入重复键。重复键值为 (000000003414)。注意我没有更改卡的详细信息,只更改了客户。 我看过这个帖子:https://blogs.msdn.microsoft.com/azuremobile/2014/06/18/insertupdate-data-with-1n-relationship-using-net-backend-azure-mobile-services/ 然而,它似乎过于复杂,我不确定这是否是我所追求的……有人知道发生了什么吗?

【问题讨论】:

  • 我怀疑您正在查看实体框架问题,因为 Id 是一个字符串 - 而不是一个 int。在 Customer 对象中将适当的 CardId 设置为字符串,然后通过 ForeignKey 注释链接,也许?
  • 移动服务要求 Id 为字符串,不知道为什么...我的控制器实现只是在您提供移动服务后端时对示例解决方案提供的函数的重命名...
  • 您在PatchCustomer 上设置了断点吗?还是再次点击插入?
  • 我在 PatchCustomer 上放了一个断点,它正确地击中了它。然后它正在调用 UpdateAsync 并返回如上所述的错误...

标签: c# sqlite azure azure-mobile-services


【解决方案1】:

有很多可能出错的事情:也许您的客户端实际上正在执行另一个插入而不是更新,这就是您会收到 409 冲突异常的原因。或者,插入成功但响应丢失的可能性较小,因此客户端将重试插入,并会得到异常。

或者,问题可能出在表之间的关系上。要调试这个,首先你应该记录你的传出请求,这样你就可以看到发生了什么。如果您的客户发送的是插入而不是更新,您会在日志中看到这一点。见Log outgoing requests in managed client (Xamarin, Windows)

然后,您可以将调试器附加到您的远程服务或本地运行的服务,以查看发生实体框架验证错误的原因。

顺便说一句,如果您要进行离线同步,您还应该添加冲突处理代码。这是一个处理 409(插入成功且响应丢失的情况)和 412 前置条件失败(当两个客户端尝试更新相同数据时)的示例:https://github.com/lindydonna/xamarin-forms-offline-sync/blob/master/XamarinFormsOffline/SyncHandler.cs#L23

【讨论】:

  • 谢谢,如果需要,我会尝试您的调试建议并在原始问题中添加更多细节。我知道冲突处理,但目前,这种“冲突”会阻止除了创建新记录之外的任何东西,这会破坏同步对象......
  • 你的帖子很有帮助!谢谢!
【解决方案2】:

目前使用 SQLite 作为中介时,Azure App Services(移动应用程序)似乎无法处理外键。因此,唯一的方法是将表作为客户端站点上的 2 个独立实体处理(您可以选择将外键保留在服务端,但这会导致尝试使用外键查询数据时出现问题) .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多