无法确定 OR 的主端 “值不能为空,参数名称'键'”

本文关键字:参数 值不能为空 OR 不能 无法确定 | 更新日期: 2023-09-27 18:35:39

我已经尝试了StackOverflow中的几乎所有内容来防止这些错误。我不知道我做错了什么。当我开始进行一些更改以删除一个错误时,会出现第二个错误,反之亦然。我不知道它是否连接到DB,或者它可以初始化DB,或者不能。看起来我的数据库文件是空的 - 我正在使用 SQLite,我想使用 EF 的代码优先机制。

我的代码

using System.Data.Entity;
using ControlCenter;
namespace ControlCenter
{
    public class IncomingMessaggesContext: DbContext
    {
        public DbSet<UnifiedPositionMessage> UnifiedPositionMessages { get; set; }
        public DbSet<MessageDescription> MessageDescriptions { get; set; }
        static IncomingMessaggesContext()
        {
            Database.SetInitializer<IncomingMessaggesContext>(null);
        }
    }
}

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ControlCenter.CommunicationGateway
{
    using System;
    using TrackingDevices.Positioning;
     public class UnifiedPositionMessage
     {   
         public int Id { get; set; }
         public uint DeviceID { get; set; }
         public DateTime ReceiveTime { get; set; }
         public PositionBase DevicePosition { get; set; }
         public object UserPayload { get; set; }
         public int MessageDescriptionId { get; set; }
        [ForeignKey("Id")]
        [Required]
        public virtual MessageDescription MessageDescription { get; set; }
     }
     public class MessageDescription
     {
         public int Id { get; set; }
         public bool IsMessageValid { get; set; }
         public virtual UnifiedPositionMessage UnifiedPositionMessage { get; set; }
     }
}

调用数据库

using (var db = new IncomingMessaggesContext()  )
{
    var msgDesc = new MessageDescription() {IsMessageValid = true, Id = 0, UnifiedPositionMessage = e.Frame};
    db.MessageDescriptions.Add(msgDesc);
    db.UnifiedPositionMessages.Add(e.Frame);
    db.SaveChanges();
}

和连接设置

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <entityFramework>
    <connectionStrings>
      <add name="IncomingMessaggesContext"
       connectionString="Data Source=c:'temp'Messages.db;"
       providerName="System.Data.SQLite" />
    </connectionStrings>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <add name="SQLite Data Provider"
            invariant="System.Data.SQLite"
            description="Data Provider for SQLite"
            type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
    </DbProviderFactories>
  </system.data>
</configuration>

无法确定 OR 的主端 “值不能为空,参数名称'键'”

您在这里定义了一个 1 ( MessageDescription ) : 0..1 (UnifiedPositionMessage ) 关联。

EF 要做的是在一个表中定义一个主键,该主键同时是另一个表的外键。在您的情况下,UnifiedPositionMessage将有一个指向 MessageDescription.Id 的非自动递增 Id 字段,这是一个自动递增的标识列。因此,任何UnifiedPositionMessage记录只有在其MessageDescription存在时才能存在。这是由 [Required] 属性强制执行的。

在这种情况下,实体中显式外键字段是没有用的:只有一个 FK 也是 PK,因此您将永远无法设置它。

因此,可以从模型中删除MessageDescriptionId,然后告诉 EF 如何映射实体:

modelBuilder.Entity<UnifiedPositionMessage>()
            .HasRequired(u => u.MessageDescription)
            .WithOptional(md => md.UnifiedPositionMessage);

(这是在DbContext.OnModelCreating覆盖中)

这可能是因为 Id 不能为 0!

var msgDesc = new MessageDescription() {IsMessageValid = true, Id = 0, UnifiedPositionMessage = e.Frame};

您可以将 msgDesc 设置为

var msgDesc = new MessageDescription {IsMessageValid = true, UnifiedPositionMessage = e.Frame};

因此,您在数据库中的记录都将具有唯一的 Id。

这不是结构体!public PositionBase DevicePosition { get; set; }.根据以下规则更改它:

  public class PositionBase
  {
    public DateTime GPSTime { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    public float Speed { get; set; }    // [km/h]
    public float Course { get; set; }   // [°]
}

public class PositionBase
{
    public int Id { get; set; }
    public DateTime GPSTime { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    public float Speed { get; set; }    // [km/h]
    public float Course { get; set; }   // [°]
    [ForeignKey("Id")]
    [Required]
    public virtual UnifiedPositionMessage UnifiedPositionMessage { get; set; }
}

并将其添加到 DbContext 可以解决问题。

public DbSet<PositionBase> PositionBases { get; set; }

第二个挑战是 EF 不支持对象类型,因此也可能导致问题!