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

136 views Asked by At

I have a file table where I am adding a FK to a module table to add in which module it is coming from.

When we create the record into FileSystemItems, we need to also update FileSystemItemsDatas as well.

We do this with the below code:

        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;
        }

Then I'm seeing this error though:

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 ---

I know that I am adding into FileSytemItemsData via my navigation property, but how to I make sure I do not update the .Modules navigation property, because I do not need to in this case.

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 code:

            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);
            });
1

There are 1 answers

1
ttaylor27272727 On BEST ANSWER

From Progman

I did not need to set the Module and FileSystemItemData in my constructor for FileSystemItems:

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