英孚核心 |需要使用导航 属性 来更新一个 属性,而不是另一个(模块)

EF Core | Need to use Navigation property for update on one property, but not another (Modules)

我有一个文件 table,我在其中将 FK 添加到模块 table 以添加它来自哪个模块。

当我们将记录创建到 FileSystemItems 中时,我们还需要更新 FileSystemItemsDatas。

我们用下面的代码来做到这一点:

        public async Task<int> CreateFileSystemItem(FileSystemItemCreateDTO fileSystemItem)
        {
            if (fileSystemItem == null)
            {
                throw new ArgumentNullException(nameof(fileSystemItem));
            }

            var fileSystemItemToCreate = new FileSystemItems()
            {
                FileName = fileSystemItem.FileName,
                FileType = fileSystemItem.FileType,
                IsFolder = fileSystemItem.IsFolder,
                LastWriteTime = fileSystemItem.LastWriteTime,
                ParentId = fileSystemItem.ParentId,
                FileMetadata = fileSystemItem.FileMetadata,
                ModuleId = fileSystemItem.ModuleId,
            };

            fileSystemItemToCreate.FileSystemItemData.FileData = fileSystemItem.FileData;

            BIContext.FileSystemItems.Add(fileSystemItemToCreate);

            await SaveChangesAsync().ConfigureAwait(false);

            return fileSystemItemToCreate.FileId;
        }

然后我看到了这个错误:

Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'DisplayName', table 'Core.Modules'; column does not allow nulls. INSERT fails.
The statement has been terminated.
   at System.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__180_0(Task`1 result)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---

我知道我正在通过我的导航 属性 添加到 FileSytemItemsData,但是如何确保我不更新 .Modules 导航 属性,因为我不需要在这个案例.

FileSystemItems.cs

/// <summary>
    /// File System Item
    /// </summary>
    public partial class FileSystemItems
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="FileSystemItems"/> class.
        /// </summary>
        public FileSystemItems()
        {
            ItemChildren = new HashSet<FileSystemItems>();
            FileSystemItemData = new FileSystemItemDatas();
            Module = new Modules();
        }

        /// <summary>
        /// Gets or sets the file identifier.
        /// </summary>
        /// <value>
        /// The file identifier.
        /// </value>
        public int FileId { get; set; }

        /// <summary>
        /// Gets or sets the parent identifier.
        /// </summary>
        /// <value>
        /// The parent identifier.
        /// </value>
        public int? ParentId { get; set; }

        /// <summary>
        /// Gets or sets the name of the file.
        /// </summary>
        /// <value>
        /// The name of the file.
        /// </value>
        public string FileName { get; set; }

        /// <summary>
        /// Gets or sets the type of the file.
        /// </summary>
        /// <value>
        /// The type of the file.
        /// </value>
        public string FileType { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is folder.
        /// </summary>
        /// <value>
        ///   <c>true</c> if this instance is folder; otherwise, <c>false</c>.
        /// </value>
        public bool IsFolder { get; set; }

        /// <summary>
        /// Gets or sets the last write time.
        /// </summary>
        /// <value>
        /// The last write time.
        /// </value>
        public DateTime LastWriteTime { get; set; }

        /// <summary>
        /// Gets or sets the file system item data identifier.
        /// </summary>
        /// <value>
        /// The file system item data identifier.
        /// </value>
        public int? FileSystemItemDataId { get; set; }

        /// <summary>
        /// Gets or sets the module identifier.
        /// </summary>
        /// <value>
        /// The module identifier.
        /// </value>
        public int? ModuleId { get; set; }

        /// <summary>
        /// Gets or sets the file metadata.
        /// </summary>
        /// <value>
        /// The file metadata.
        /// </value>
        public string FileMetadata { get; set; }

        /// <summary>
        /// Gets or sets the file system item data.
        /// </summary>
        /// <value>
        /// The file system item data.
        /// </value>
        public FileSystemItemDatas FileSystemItemData { get; set; }

        /// <summary>
        /// Gets or sets the item children.
        /// </summary>
        /// <value>
        /// The item children.
        /// </value>
        public virtual ICollection<FileSystemItems> ItemChildren { get; set; }

        /// <summary>
        /// Gets or sets the parent item.
        /// </summary>
        /// <value>
        /// The parent item.
        /// </value>
        public virtual FileSystemItems ParentItem { get; set; }

        /// <summary>
        /// Gets or sets the module.
        /// </summary>
        /// <value>
        /// The module.
        /// </value>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "It's a Module")]
        public virtual Modules Module { get; set; }
    }

Modules.cs

    /// <summary>
    /// Module
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "It's a Module")]
    [Table("Modules", Schema = "Core")]
    public partial class Modules
    {
        /// <summary>
        /// Gets or sets the module identifier.
        /// </summary>
        /// <value>
        /// The module identifier.
        /// </value>
        public int ModuleId { get; set; }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>
        /// The name.
        /// </value>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the display name.
        /// </summary>
        /// <value>
        /// The name.
        /// </value>
        public string DisplayName { get; set; }

        /// <summary>
        /// Gets or sets the extension identifier.
        /// </summary>
        /// <value>
        /// The extension identifier.
        /// </value>
        public int ExtensionId { get; set; }

        /// <summary>
        /// Gets or sets the file system items.
        /// </summary>
        /// <value>
        /// The file system items.
        /// </value>
        public virtual ICollection<FileSystemItems> FileSystemItems { get; set; }
    }

FileSystemItemsDatas.cs

    /// <summary>
    /// File system item data
    /// </summary>
    public partial class FileSystemItemDatas
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="FileSystemItemDatas"/> class.
        /// </summary>
        public FileSystemItemDatas()
        {
            FileSystemItems = new HashSet<FileSystemItems>();
        }

        /// <summary>
        /// Gets or sets the file data identifier.
        /// </summary>
        /// <value>
        /// The file data identifier.
        /// </value>
        public int FileDataId { get; set; }

#pragma warning disable CA1819 // Properties should not return arrays
                              /// <summary>
                              /// Gets or sets the file data.
                              /// </summary>
                              /// <value>
                              /// The file data.
                              /// </value>
        public byte[] FileData { get; set; }
#pragma warning restore CA1819 // Properties should not return arrays

        /// <summary>
        /// Gets or sets the file system items.
        /// </summary>
        /// <value>
        /// The file system items.
        /// </value>
        public ICollection<FileSystemItems> FileSystemItems { get; set; }
    }

模型生成器代码:

            modelBuilder.Entity<FileSystemItemDatas>(entity =>
            {
                entity.HasKey(e => e.FileDataId);
            });

            modelBuilder.Entity<FileSystemItems>(entity =>
            {
                entity.HasKey(e => e.FileId);

                entity.Property(e => e.FileName)
                    .IsRequired()
                    .HasMaxLength(255)
                    .IsUnicode(false);

                entity.Property(e => e.FileType)
                    .IsRequired()
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.FileMetadata).IsRequired().HasColumnType("nvarchar(max)").HasDefaultValue("[{}]");

                entity.Property(e => e.LastWriteTime).HasColumnType("datetime");

                entity.HasOne(d => d.FileSystemItemData)
                   .WithMany(p => p.FileSystemItems)
                   .HasForeignKey(d => d.FileSystemItemDataId)
                   .HasConstraintName("FK_FileSystemItems_FileSystemItemDatas");

                entity.HasOne(d => d.Module)
                    .WithMany(p => p.FileSystemItems)
                    .HasForeignKey(d => d.ModuleId)
                    .HasConstraintName("FK_FileSystemItems_ModuleId");

                entity.HasOne(d => d.ParentItem)
                    .WithMany(p => p.ItemChildren)
                    .HasForeignKey(d => d.ParentId)
                    .HasConstraintName("FK_FileSystemItems_FileSystemItems");

                entity.HasOne(d => d.ParentItem)
                    .WithMany(p => p.ItemChildren)
                    .HasForeignKey(d => d.ParentId)
                    .HasConstraintName("FK_FileSystemItems_FileSystemItems");
            });

            modelBuilder.Entity<Modules>(entity =>
            {
                entity.HasKey(e => e.ModuleId);

                entity.Property(e => e.Name)
                    .IsRequired()
                    .HasMaxLength(200)
                    .IsUnicode(false);

                entity.Property(e => e.DisplayName)
                    .IsRequired()
                    .HasMaxLength(200)
                    .IsUnicode(false);
            });

来自Progman

我不需要在 FileSystemItems 的构造函数中设置 Module 和 FileSystemItemData:

        /// <summary>
        /// Initializes a new instance of the <see cref="FileSystemItems"/> class.
        /// </summary>
        public FileSystemItems()
        {
            ItemChildren = new HashSet<FileSystemItems>();
        }