【问题标题】:.Net EF I can't update the data in my db. Getting an Invalid column name exception.Net EF 我无法更新数据库中的数据。获取无效的列名异常
【发布时间】:2021-01-06 02:20:20
【问题描述】:

这是我用于更新的请求处理程序:

public async Task<UpdateEmployeesResponse> Handle(UpdateEmployeesRequest request, CancellationToken cancellationToken)
{
    var data = _context.Employees
                       .FirstOrDefault(person => person.Auth0ID == request.UpdateEmployee.Auth0Id);

    var skill = _context.Skill.FirstOrDefault(skill => skill.Id == request.UpdateEmployee.SkillLevel.Id);

    var employeeProgrammingLanguages = _context.EmployeeProgrammingLanguages.Where(_ => _.EmployeeId == data.Id);
    var programmingLanguagesList = new List<ProgrammingLanguage>();

    var element = 0;

    foreach (var programmingLanguage in request.UpdateEmployee.ProgramLanguages)
    {
        while (element < employeeProgrammingLanguages.Count())
        {
            var eProg = employeeProgrammingLanguages.ToList()[element];
            var prog = _context.ProgrammingLanguages.FirstOrDefault(_ => _.Id == eProg.ProgrammingLanguageId);//employeeProgrammingLanguages.ElementAtOrDefault(element).ProgrammingLanguageIdFirstOrDefault(_ => _.Id == eProg.ProgrammingLanguageId); 

            if (programmingLanguage.Name != "")
            {
                prog.Name = programmingLanguage.Name;
            }

            prog.Skill = programmingLanguage.Skill;

            programmingLanguagesList.Add(prog);

            _context.ProgrammingLanguages.Update(prog);
            element++;
        }
    }

    data.UpdateEmployeeInformation(request.UpdateEmployee.FirstName, request.UpdateEmployee.LastName, request.UpdateEmployee.Auth0Id, request.UpdateEmployee.Township, request.UpdateEmployee.Description, skill, programmingLanguagesList);

    _context.Employees.Update(data);

    await _context.SaveChangesAsync(cancellationToken);

    return new UpdateEmployeesResponse { UpdateEmployee = request.UpdateEmployee };
}

仅使用员工的基本信息更新data.UpdateEmployeeInformation,但是当我尝试更改关联表时,我收到一个错误,您可以在屏幕截图中看到。

https://i.stack.imgur.com/MtCMX.png

错误:

Microsoft.Data.SqlClient.SqlException (0x80131904):列名“EmployeeId”无效。

在 Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException 异常,布尔型 breakConnection,Action1 wrapCloseInAction) at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction)
在 Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,布尔调用者HasConnectionLock,布尔异步关闭) 在 Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean & dataReady) 在 Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData() 在 Microsoft.Data.SqlClient.SqlDataReader.get_MetaData() 在 Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,字符串 resetOptionsString,布尔 isInternal,布尔 forDescribeParameterEncryption,布尔 shouldCacheForAlwaysEncrypted) 在 Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,布尔 returnStream,布尔 isAsync,Int32 超时,任务和任务,布尔 asyncWrite,布尔 inRetry,SqlDataReader ds,布尔 describeParameterEncryptionRequest) 在 Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,布尔 returnStream,TaskCompletionSource1 completion, Int32 timeout, Task&amp; task, Boolean&amp; usedCache, Boolean asyncWrite, Boolean inRetry, String method) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) at Microsoft.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.ExecuteReader() at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.InitializeReader(DbContext _,布尔结果) 在 Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState 状态,Func3 operation, Func3 verifySucceeded) 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.MoveNext() at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable1 来源) 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](表达式查询) 在 Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](表达式表达式) 在 System.Linq.Queryable.FirstOrDefault[TSource](IQueryable1 source, Expression1 谓词) 在 C:\Users\Abdurrahman\Desktop\School\APLessen\IT-Case\AP-ITCASE\Involved-ITCase-AP\Involved.Cv 中的 Involved.Cv.Service.Employee.UpdateEmployeesRequestHandler.Handle(UpdateEmployeesRequest request, CancellationToken cancelToken) .Service\Employee\UpdateEmployeesRequestHandler.cs:第 49 行 在 MediatR.Pipeline.RequestExceptionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 下一个) 在 MediatR.Pipeline.RequestExceptionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 下一个) 在 MediatR.Pipeline.RequestExceptionActionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 下一个) 在 MediatR.Pipeline.RequestExceptionActionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 下一个) 在 MediatR.Pipeline.RequestPostProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 下一个) 在 MediatR.Pipeline.RequestPreProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 下一个) 在 C:\Users\Abdurrahman\Desktop\School\APLessen\IT-Case\AP-ITCASE\Involved-ITCase-AP\Involved.Cv 中的 Involved.Cv.Host.Controllers.EmployeeController.Update(UpdateEmployeeInformation model, CancellationToken cancelToken) .Host\Controllers\EmployeeController.cs:第 40 行 在 lambda_method(闭包,对象) 在 Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult() 在 Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper 映射器,ObjectMethodExecutor 执行器,对象控制器,对象 [] 参数) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker 调用程序,ValueTask`1 actionResultValueTask) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker 调用程序,任务 lastTask,下一个状态,作用域范围,对象状态,布尔 isCompleted) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed 上下文) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(状态&下一个,范围&范围,对象&状态,布尔& isCompleted) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker 调用程序,任务 lastTask,下一个状态,作用域范围,对象状态,布尔 isCompleted) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed 上下文) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(状态&下一个,范围&范围,对象&状态,布尔& isCompleted) 在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker 调用程序,任务任务,IDisposable 范围) 在 Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(端点端点,任务 requestTask,ILogger 记录器) 在 Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext 上下文) 在 Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext 上下文) 在 Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) 在 Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext,ISwaggerProvider swaggerProvider) 在 Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文) ClientConnectionId:186bcee6-7dc4-4984-98ed-d67514c1117b 错误号:207,状态:1,类:16

EmployeeProgrammingLanguage 类:

public class EmployeeProgrammingLanguage
{
        public int Id { get; private set; }
        public int? EmployeeId { get; private set; }
        public int? ProgrammingLanguageId { get; private set; }

        public EmployeeProgrammingLanguage(int? employeeId, int? programmingLanguageId)
        {
            EmployeeId = employeeId;
            ProgrammingLanguageId = programmingLanguageId;
        }
}

ProgrammingLanguage 类:

public class ProgrammingLanguage
{
        public int Id { get; private set; }
        public string Name { get; set; }
        public double Skill { get; set; }

        public ProgrammingLanguage(string name, double skill)
        {
            Name = name;
            Skill = skill;
        }
}

感谢您的帮助!如果需要,我会添加额外的信息,不确定这是否足以识别问题。

数据库脚本:

Create.Table("ProgrammingLanguage")
                .WithColumn("Id").AsInt32().Identity().PrimaryKey()
                .WithColumn("Name").AsString().NotNullable()
                .WithColumn("Skill").AsDouble().NotNullable();

Create.Table("EmployeeProgrammingLanguage")
                .WithColumn("Id").AsInt32().Identity().PrimaryKey()
                .WithColumn("EmployeeId").AsInt32().ForeignKey("Employee", "Id")
                .WithColumn("ProgrammingLanguageId").AsInt32().ForeignKey("ProgrammingLanguage", "Id");

Create.Table("Employee")
                .WithColumn("Id").AsInt32().Identity().PrimaryKey()
                .WithColumn("FirstName").AsString(50).NotNullable()
                .WithColumn("LastName").AsString(50).NotNullable()
                .WithColumn("Email").AsString().NotNullable()
                .WithColumn("BirthDate").AsDate().NotNullable()
                .WithColumn("UpdatedTime").AsDate().Nullable()
                .WithColumn("Auth0ID").AsString(50).NotNullable()
                .WithColumn("Township").AsString(50).NotNullable()
                .WithColumn("Description").AsString().Nullable()
                .WithColumn("SkillLevelId").AsInt32().Nullable().ForeignKey("SkillLevel", "Id");

【问题讨论】:

  • 您好,错误提示“EmployeeId”无效。您的 db 列中一定有错误。
  • 嗨,我检查了很多次,但没有运气,我的数据库中的所有内容在命名方面都是正确的。
  • 能分享一下db脚本吗?
  • 我是使用数据库和实体框架的新手,我用我希望数据库脚本编辑了这篇文章。
  • 您使用的是两个不同的数据库吗?

标签: c# .net entity-framework linq


【解决方案1】:

这看起来有点可疑。查看实体和数据库“脚本”(迁移?)

public class EmployeeProgrammingLanguage
    {
        public int Id { get; private set; }
        public int? EmployeeId { get; private set; }
        public int? ProgrammingLanguageId { get; private set; }

        public EmployeeProgrammingLanguage(int? employeeId, int? programmingLanguageId)
        {
            EmployeeId = employeeId;
            ProgrammingLanguageId = programmingLanguageId;
        }
    }

Create.Table("EmployeeProgrammingLanguage")
    .WithColumn("Id").AsInt32().Identity().PrimaryKey()
    .WithColumn("EmployeeId").AsInt32().ForeignKey("Employee", "Id")             
    .WithColumn("ProgrammingLanguageId").AsInt32().ForeignKey("ProgrammingLanguage", "Id");

你用什么来映射?您的实体没有使用属性,您是使用 OnModelCreating 或 EntityTypeConfiguration 类,还是依赖 EF 的约定来解决问题?

我看到的一些潜在问题:

  1. EmployeeProgrammingLanguage 上的私有设置器并依赖于构造函数初始化。实体应使用公共或内部设置器,因为 EF 需要管理更新的 FK。
  2. 此链接实体中没有 Employee 或 ProgrammingLanguage 的导航属性。迁移脚本提到 EmployeeId 是 Employee 的外键,但同时您没有利用此链接的任何导航属性。
  3. 多对多链接实体上的可空 FK。 &
  4. 多对多链接实体被视为顶级实体。 (DbContext 中的 DbSet)

多对多链接表通常通过导航从关系的一方或双方访问。在许多情况下,这些表仅包含作为复合 PK 的相关实体的 FK。使用 EF 6,此表甚至不需要映射到实体,它可以完全在幕后进行管理。 AFAIK 在没有加入实体的情况下,EF Core 尚不支持此功能。

没有加入实体的EF6:

public class Employee
{
    // ...
    public virtual ICollection<ProgrammingLanguage> ProgrammingLanguages { get; set; } = new List<ProgrammingLanguage>();
}

public class ProgrammingLanguage
{
    // ...
    public virtual ICollection<Employee> Employees { get; set; } = new List<Employee>();
}

使用连接实体(EF Core 或 EF6,您需要在连接表中添加其他属性)

public class Employee
{
    // ...
    public virtual ICollection<EmployeeProgrammingLanguage> EmployeeProgrammingLanguages { get; set; } = new List<EmployeeProgrammingLanguage>();
}

public class ProgrammingLanguage
{
    // ...
    public virtual ICollection<EmployeeProgrammingLanguage> EmployeeProgrammingLanguages { get; set; } = new List<EmployeeProgrammingLanguage>();
}

使用连接实体,FK 列将不能为空,并且可以使用复合键或 PK 列。 (即“Id”)加入实体的缺点只是增加了“通过”加入实体以获取所需详细信息的麻烦。使用 EF6 并避免加入实体,审查员工的编程语言将是 按照.SelectMany(e =&gt; e.ProgrammingLanguages) 对于加入实体,它将是 .SelectMany(e =&gt; e.EmployeeProgrammingLanguages.Select(epl =&gt; epl.ProgrammingLanguage))

您通常不会通过DbContext 上的DbSet 访问EmployeeProgrammingLanguage。

【讨论】:

    猜你喜欢
    • 2017-03-16
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多