我使用数据库优先方法来使用 EF Core 和 SQL Server。我可以使用
dotnet-ef
CLI 对表和视图进行逆向工程。在逆向工程时,它保留了视图中表中选择列的可为空性。
即,我有以下 SQL Server 架构:
CREATE TABLE [dbo].[Terminal] (
[Id] int NOT NULL IDENTITY,
[Tid] nvarchar(max) NOT NULL,
[ActivedAt] datetime2 NULL,
CONSTRAINT [PK_Terminal] PRIMARY KEY ([Id])
);
CREATE OR ALTER VIEW [dbo].[TerminalView]
WITH SCHEMABINDING
AS
SELECT [t].[Id],
[t].[Tid],
ISNULL(CAST(IIF([t].[ActivedAt] IS NULL, 0, 1) AS BIT), 0) AS [IsActive]
FROM [dbo].[Terminal] AS [t];
当对这个模式进行逆向工程时,我得到:
public partial class Terminal
{
public int Id { get; set; }
public string Tid { get; set; } = null!;
public DateTime? ActivedAt { get; set; }
}
public partial class TerminalView
{
public int Id { get; set; }
public string Tid { get; set; } = null!;
public bool IsActive { get; set; }
}
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
namespace Npgsql.Scaffolding.Lab.Models;
public partial class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public virtual DbSet<Terminal> Terminals { get; set; }
public virtual DbSet<TerminalView> TerminalViews { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Terminal>(entity =>
{
entity.ToTable("Terminal");
entity.Property(e => e.Id).HasColumnName("Id");
entity.Property(e => e.ActivedAt).HasColumnName("ActivedAt");
entity.Property(e => e.Tid).HasColumnName("Tid");
});
modelBuilder.Entity<TerminalView>(entity =>
{
entity
.HasNoKey()
.ToView("TerminalView");
entity.Property(e => e.Id)
.ValueGeneratedOnAdd()
.HasColumnName("Id");
entity.Property(e => e.IsActive).HasColumnName("IsActive");
entity.Property(e => e.Tid).HasColumnName("Tid");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
当我迁移到 PostgreSQL 架构时:
CREATE TABLE IF NOT EXISTS public.terminal
(
id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
tid text COLLATE pg_catalog."default" NOT NULL,
actived_at timestamp with time zone,
CONSTRAINT "PK_terminal" PRIMARY KEY (id)
)
CREATE OR REPLACE VIEW public.terminal_view
WITH (
check_option=cascaded
) AS
SELECT id,
tid,
actived_at IS NOT NULL AS is_active
FROM terminal;
当我进行逆向工程时,
TerminalView
可空性不会持续存在。所有属性现在都可以为空。
public partial class TerminalView
{
public int? Id { get; set; }
public string? Tid { get; set; }
public bool? IsActive { get; set; }
}
有人遇到过这样的问题吗?有什么解决办法吗?
无论如何,PostgreSQL 视图中的列始终显示为
NOT NULL
。没有办法改变这一点(除了改变 PostgreSQL)。视图只是一个带有名称的查询 - 它是强制执行约束的基础表。
我想说这是你的工具的问题,该工具可能是为了利用 Microsoft SQL Server 的特殊功能而编写的。