更新列

时间:2019-07-16 13:59:41

标签: c# sql aws-lambda entity-framework-core

目前,我正在寻找一个端点并将数据存储在以下实体框架核心类中:

using System;
using System.Collections.Generic;
using System.Text;

namespace [removed].[removed].DataAccess.Entities
{
    public class ResourceRegistration
    {
        public Guid Id { get; set; }
        public Guid? ResourceId { get; set; }
        public string ExternalId { get; set; }
        public Guid? RegistrationStatusId { get; set; }
        public Guid? EventId { get; set; }
        public Guid? CourseId { get; set; }
        public Guid? ResourceDocumentId { get; set; }
        public double? Score { get; set; }
        public string Uri { get; set; }
        public DateTime? CompletedOn { get; set; }
    }
}

在某些时候,我们的DBA将ExternalId表示为一个Int值,这很可能是因为ExternalId是多态的,但是在我的特定情况下,它是Guid。作为一种折衷,他将数据库中的列从int更改为nvarchar(64)值。

现在,我遇到一个可疑的问题,当通过AWS .NET Mock Lambda测试工具调用SaveChangesAsync方法时,我收到以下错误:

  

System.Data.SqlClient.SqlException:转换时转换失败   数据类型为int的nvarchar值“ [已删除guid]”。

令人怀疑的是,由于尝试将Guid转换为 old 数据类型而导致转换失败。

我已经确认该列在数据库中被表示为nvarchar(64)。我还确认我的连接字符串指向正确的数据库。

正在使用的模拟方法:

private async Task UpsertRegistrations(Registration[] registrations, Guid documentTemplateId)
{
    DbContextOptions registrationOptions = new DbContextOptionsBuilder()
                    .UseSqlServer(this.[variable for db])
                    .Options;

    using (ArloContext db = new ArloContext(registrationOptions))
    {
        foreach (Registration registration in registrations)
        {
            ResourceRegistration resourceRegistration = db.ResourceRegistrations.SingleOrDefault(r => r.ExternalId == registration.UniqueIdentifier.ToString());
            AbbreviatedResource contact = db.Resources.FromSql("SELECT Id, Email FROM Resources WHERE Email = {0}", registration.Contact.Email).SingleOrDefault();
            RegistrationStatus status = db.RegistrationStatuses.SingleOrDefault(s => s.Name == registration.Status);
            DataAccess.Entities.Event _event = null;
            if (registration.Event != null)
            {
                _event = db.Events.SingleOrDefault(e => e.ExternalId == registration.Event.UniqueIdentifier.GetValueOrDefault());
            }
            AsyncTask asyncTask = _arloService.GetAsyncTask(registration, documentTemplateId);

            List<string> errorMessages = new List<string>();
            if (contact == null)
            {
                errorMessages.Add("During the UpsertRegistrations, the Contact was not found with the following Email: " + registration.Contact.Email);
            }
            if (status == null)
            {
                errorMessages.Add("During the UpsertRegistrations, the RegistrationStatus was not found with the following Name: " + registration.Status);
            }
            if (_event == null)
            {
                if (registration.Event == null)
                {
                    errorMessages.Add("During the UpsertRegistrations, the Event was null for the Registration with the Arlo RegistrationId: " + registration.RegistrationId);
                }
                else
                {
                    errorMessages.Add("During the UpsertRegistrations, the Event was not found with the following ExternalId: " + registration.Event.UniqueIdentifier);
                }
            }

            if (errorMessages.Any())
            {
                LambdaLogger.Log(string.Join(". ", errorMessages.ToArray()));
                continue;
            }

            string externalRegistrationId = registration.UniqueIdentifier.ToString();
            string certificateUrl = null;
            if (asyncTask != null && asyncTask.CertificateDownloadUrls != null)
            {
                certificateUrl = asyncTask.CertificateDownloadUrls.FirstOrDefault();
            }

            if (resourceRegistration == null)
            {
                // insert
                resourceRegistration = new ResourceRegistration()
                {
                    Id = Guid.NewGuid(),
                    ResourceId = contact.Id,
                    RegistrationStatusId = status.Id,
                    CourseId = null,
                    EventId = _event.Id,
                    ExternalId = externalRegistrationId,
                    Score = null,
                    Uri = certificateUrl,
                };
                db.ResourceRegistrations.Add(resourceRegistration);
            }
            else
            {
                // update
                resourceRegistration.ResourceId = contact.Id;
                resourceRegistration.RegistrationStatusId = status.Id;
                resourceRegistration.EventId = _event.Id;
                resourceRegistration.ExternalId = externalRegistrationId;
                resourceRegistration.Uri = certificateUrl;
            }
        }

        await db.SaveChangesAsync();
    }
}

1 个答案:

答案 0 :(得分:0)

与同事进行橡皮鸭训练后,我发现了自己的问题。显然存在一个名为18, 2的时态表,它表示历史数据。在我要写入的表上设置了一个触发器,该触发器会自动将相同的数据写入时态表。

之所以难以调试,是因为返回的错误消息不包含引发转换错误的表的表名。

虽然此错误相对少见,但这是我们调试问题的方法:

  1. 我们检查了连接字符串。检查。
  2. 我们检查了表的属性,以确认该列的 数据类型是预期的数据类型。检查。
  3. 我们检查了C#类的属性,以确认 属性的数据类型与相应列的数据类型匹配 在数据库中。检查。
  4. 我们检查了表的触发器,以确认是否创建/更新 触发任何其他SQL。我们发现已设置触发器以写入protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); modelBuilder.Entity<Table>(entity => { entity.ToTable("table"); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Salary) .HasColumnName("salary") .HasColumnType("decimal(18, 0)") .HasDefaultValueSql("0"); }); }
  5. 我们检查了Histories.Registrations上的ExternalId列的属性,以确认该列的数据类型是预期的数据类型。宾果游戏!

最后一步是当我们发现错误时。