首页 > 解决方案 > ASP.Net Core,创建具有复杂数据类型属性的模型

问题描述

在 Asp.Net Core 中,我创建了以下模型:

[Keyless]
public class NameSet
{
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public NameSet Name { get; set; }
    public string Mobile { get; set; }
    public string Email { get; set; }
    public bool IsActive { get; set; }
}

在 ApplicationDbContext 类中:

public DbSet<Customer> Customers { get; set; }

现在,我希望我的数据库中的表如下所示:

ID 中间名字 移动的 电子邮件 活跃

当我尝试上述方法时,它在添加迁移期间给了我一个错误:

Unable to determine the relationship represented by navigation 'Customer.Name' of type 'NameSet'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

请建议,我怎样才能用“NameSet”属性使我的“CustomerModel”成熟,所以我可以这样做。

标签: asp.net-core

解决方案


您可以使用OwnsOne. 下面的代码使用 EF Core 3.1.11 进行了测试。

这是一个完整的示例,它将完全创建您想要的表:

using System;
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;

namespace MyConsoleApp
{
    class Program : IDesignTimeDbContextFactory<MyDbContext>
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }

        public MyDbContext CreateDbContext(string[] args)
        {
            var configurationBuilder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

            IConfigurationRoot configuration = configurationBuilder.Build();
            string connectionString = configuration.GetConnectionString("Storage");

            DbContextOptionsBuilder<MyDbContext> optionsBuilder = new DbContextOptionsBuilder<MyDbContext>()
                .UseSqlServer(connectionString);

            return new MyDbContext(optionsBuilder.Options);
        }
    }

    public class MyDbContext : DbContext
    {
        public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }
        public DbSet<Customer> Customers { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.Entity<Customer>().OwnsOne(p => p.Name, sa =>
            {
                sa.Property(p => p.FirstName).HasColumnName("FirstName");
                sa.Property(p => p.LastName).HasColumnName("LastName");
                sa.Property(p => p.MiddleName).HasColumnName("MiddleName");
            });
        }

    }

    public class NameSet
    {
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }
    }

    public class Customer
    {
        public int Id { get; set; }
        public NameSet Name { get; set; }
        public string Mobile { get; set; }
        public string Email { get; set; }
        public bool IsActive { get; set; }
    }
}

从迁移生成的 SQL 将如下所示:

CREATE TABLE [dbo].[Customers](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [FirstName] [nvarchar](max) NULL,
    [MiddleName] [nvarchar](max) NULL,
    [LastName] [nvarchar](max) NULL,
    [Mobile] [nvarchar](max) NULL,
    [Email] [nvarchar](max) NULL,
    [IsActive] [bit] NOT NULL,
 CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

迁移本身将如下所示:

    migrationBuilder.CreateTable(
        name: "Customers",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("SqlServer:Identity", "1, 1"),
            FirstName = table.Column<string>(nullable: true),
            MiddleName = table.Column<string>(nullable: true),
            LastName = table.Column<string>(nullable: true),
            Mobile = table.Column<string>(nullable: true),
            Email = table.Column<string>(nullable: true),
            IsActive = table.Column<bool>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Customers", x => x.Id);
        });

推荐阅读