博客 (4)

方法一:

在 DbContext.cs 文件中找到 OnConfiguring 方法,添加代码:

#if DEBUG
    optionsBuilder.EnableSensitiveDataLogging();
    optionsBuilder.LogTo(Console.WriteLine); // 输出日志到控制台
    //optionsBuilder.LogTo(message => Debug.WriteLine(message)); // 输出日志到“输出”窗口
#endif

搞定。

若原来是 => 形式的,改为 { } 形式写法即可。


方法二:使用 Logging

打开 DbContext 文件,添加

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Debug;

optionsBuilder.UseMySql

替换为

optionsBuilder.UseLoggerFactory(MyLoggerFactory).UseMySql

添加方法

public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] {
    new DebugLoggerProvider()
});

即可在“输出”窗口看到生成的 SQL 语句了。


xoyozo 1 年前
1,350

Pomelo.EntityFrameworkCore.MySql 升级到 7.0 后出现:

System.InvalidOperationException:“The 'sbyte' property could not be mapped to the database type 'tinyint(1)' because the database provider does not support mapping 'sbyte' properties to 'tinyint(1)' columns. Consider mapping to a different database type or converting the property value to a type supported by the database using a value converter. See https://aka.ms/efcore-docs-value-converters for more information. Alternately, exclude the property from the model using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.”

对比 6.0 生成的 DbContext.cs 发现缺少了 UseLoggerFactory,按旧版修改即可。


找到 OnConfiguring 方法,上方插入:

public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] {
    new DebugLoggerProvider()
});

在 OnConfiguring 方法中将:

optionsBuilder.UseMySql("连接字符串");

改为:

optionsBuilder.UseLoggerFactory(MyLoggerFactory).UseMySql("连接字符串");


xoyozo 2 年前
1,591

开发环境正常,发布到 IIS 报错

Could not load file or assembly 'Microsoft.EntityFrameworkCore.Relational, Version=6.0.x.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. 系统找不到指定的文件。

尝试在 UI 层安装 Pomelo.EntityFrameworkCore.MySql 无果。

最终,在发布时文件发布选项中,去掉“启用 ReadyToRun 编译”就正常了。

当然这种情况不是在所有启用了 ReadyToRun 编译的项目中遇到,但该项目改为不启用 ReadyToRun 后恢复正常了,原因暂时未知。

xoyozo 3 年前
2,485

在数据库连接字符串可设置是否将 tinyint(1) 映射为 bool,否则为 sbyte:

TreatTinyAsBoolean=false/true

tinyint(1) 一般用于表示 bool 型字段,存储内容为 0 或 1,但有时候也用来存储其它数字。

以 Discuz! 的表 pre_forum_post 为例,字段 first 和 invisible 都是 tinyint(1),但 first 只储存 0 和 1,invisible 却有 -1、-5 之类的值。

因此我们一般设置 TreatTinyAsBoolean=false,程序中 first 与 invisible 均以 sbyte 处理。


设置 TreatTinyAsBoolean=true 后,EF 或 EF Core 自动将该类型映射为 bool,方便在程序中作进一步处理。

一旦设置 TreatTinyAsBoolean=true,那么所有查询结果中 tinyint(1) 字段的返回值永远只有 1 和 0(即 True/False),即使真实值为 -1,也返回 1。

因为我们必须在确保所有的 tinyint(1) 类型字段都仅表示布尔值是才设置 TreatTinyAsBoolean=true。

一旦部分 tinyint(1) 类型字段用于存放 0 和 1 以外的数,那么就应该设置 TreatTinyAsBoolean=false。


在数据库优先的项目中,以 TreatTinyAsBoolean=false 生成数据模型后,可将明确为布尔类型的字段改为 bool。列出 MySQL 数据库中所有表所有字段中类型为 tinyint(1) 的字段值


以 .edmx 为例:

在项目中搜索该字段名,在搜索结果中找到 .edmx 文件中的两处。

.edmx 文件中的注释已经表明其包含 SSDL、CSDL、C-S mapping 三块内容,

在 SSDL content 下方找到该字段:

<Property Name="字段名" Type="tinyint" Nullable="***" />

改为

<Property Name="字段名" Type="bool" Nullable="***" />


在 CSDL content 下方找到该属性:

<Property Name="属性名" Type="SByte" Nullable="***" />

改为

<Property Name="属性名" Type="Boolean" Nullable="***" />

在解决方案管理器中展开 .edmx ->库名.tt -> 表名.cs 文件,

将模型类中的属性

public sbyte invisible { get; set; }

改为

public bool invisible { get; set; }

或 sbyte? 改为 bool?。


在 EF Core 中,直接打开对应数据表的 .cs 文件,更改属性类型即可。


相关报错:

错误: 指定的成员映射无效。类型中的成员的类型“Edm.SByte[Nullable=False,DefaultValue=]”与类型中的成员的“MySql.bool[Nullable=False,DefaultValue=]”不兼容。

InvalidOperationException: The property '***' is of type 'sbyte' which is not supported by the current database provider. Either change the property CLR type, or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

尝试先连接一次能解决此问题(概率),非常的莫名其妙:

using Data.Discuz.db_bbs2021Context dbd = new();
var conn = dbd.Database.GetDbConnection();
conn.Open();
conn.Close();


参考:

https://mysqlconnector.net/connection-options/

https://stackoverflow.com/questions/6656511/treat-tiny-as-boolean-and-entity-framework-4


2023年1月注:本文适用于 Pomelo.EntityFrameworkCore.MySql 6.0,升级到 7.0 后会出现:

System.InvalidOperationException:“The 'sbyte' property could not be mapped to the database type 'tinyint(1)' because the database provider does not support mapping 'sbyte' properties to 'tinyint(1)' columns. Consider mapping to a different database type or converting the property value to a type supported by the database using a value converter. See https://aka.ms/efcore-docs-value-converters for more information. Alternately, exclude the property from the model using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.”

解决方法:https://xoyozo.net/Blog/Details/the-sbyte-property-could-not-be-mapped-to-the-database-type-tinyint-1

xoyozo 5 年前
6,741