SqlSugar简单使用记录(二)

960 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

书接上文 --> SqlSugar简单使用记录(一)

其实上文中,还是有很多缺陷的,比如

  1. 主键Id如果要自增,其类型必须为int,bigint,smallint,tinyint,deciaml或数值类型(上文中为string)
  2. 如果采用SqlServer数据库,中文会乱码,mysql不会(其他数据库未测试)
  3. 无法批量创建数据表

下面就来依次处理这些问题

注:下文所有涉及到字段类型改动(字段名称不改动),都需要手动删除原数据库或对应表,否则会报错!

主键问题

如果想要使用自增,那就需要将类型设为int,否则会报错

image.png

修改Students表

public class Students
{
    //IsPrimaryKey:主键标识;IsIdentity:数据自增
    [SugarColumn(IsPrimaryKey = true,IsIdentity = true)]
    public int Id { get; set; }
    
    public string Name { get; set; }

    public int Age { get; set; }

    public string Happy { get; set; }
}

经测试,插入数据完全没有问题,Id很有规律的自增了起来...
如此,无需手动设置Id,插入时,ORM会自动按顺序生成(从1开始,依次2,3,4,5....)仿佛很完美的解决了问题!
但是,我不喜欢这种方式 ---> 这个Id太有规律,感觉不太好,容易暴露,而且有个致命的缺陷:数据库做数据迁移时,原数据的主键会被动修改,这个太致命了
作为.NET程序员,习惯用 Guid 作为主键
那就来继续改造 Id

[SugarColumn(IsPrimaryKey = true)]//Guid不存在自增,所以IsIdentity就不需要了
public Guid Id { get; set; }

此时,在插入数据时,我可以选择不给Id赋值,主键会被自动赋值,我也可以选择手动赋值(不推荐)

//手动赋值
db.Insertable(new Students { Id = new Guid(), Name = "张三", Age = 25, Happy = "跑步" }).ExecuteCommand();

插入中文乱码问题

SqlSugar在使用SqlServer数据库时,当表中字段为string类型时,会自动创建为varchar类型

image.png

而在我插入数据中有中文时,会变成 ?? image.png 到这里我会首先怀疑是SqlSugar在执行Insertable时,生成的sql语句出了问题,我要把这个sql语句打印出来看看

如何打印sql语句呢,正好SqlSugar封装了AOP image.png 可以用OnLogExecuting将sql打印到控制台

//在SqlSugarSetup类中的 属性db > get访问器中,末尾添加
AopEvents = new AopEvents
{
    OnLogExecuting = (sql, p) =>
    {
        Console.WriteLine(sql);
        Console.WriteLine(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
    }
}

image.png 然后将运行方式从IIS改为控制台启动方式,这样控制台黑框才能在运行时弹出,sql才能从黑框中打印出来 image.png 好了,现在可以看到sql语句了 image.png 如上图,sql并没有什么毛病,去数据库看了下,string类型字段 ---> varchar
这可能就是问题所在了
我要让SqlSugar帮我将string类型改成nvarchar!
看了下SqlSugar官方文档,字段加特性呗

[SugarColumn(ColumnDataType = "Nvarchar(200)")]
public string Name { get; set; }

public int Age { get; set; }

[SugarColumn(ColumnDataType = "Nvarchar(500)")]
public string Happy { get; set; }

手动删除原数据库(删对应的表也行),然后运行,插入数据,查询,这下中文可以插入了 image.png

这个问题还有别的方式处理方式的,这里也说明下
就是修改数据库和表字段的 Collections
统一改为 Chinese_PRC_CI_AS

//修改数据库Collection
ALTER DATABASE sugartest SET SINGLE_USER WITH ROLLBACK IMMEDIATE //确保没有其他人在使用数据库
ALTER DATABASE sugartest COLLATE Chinese_PRC_CI_AS  //修改
ALTER DATABASE sugartest SET MULTI_USER //允许别人使用数据库

//修改表中对应字段:这里比较繁琐,需要一个一个写
ALTER TABLE Students ALTER COLUMN Name nvarchar(200) COLLATE Chinese_PRC_CI_AS
ALTER TABLE Students ALTER COLUMN Happy nvarchar(500) COLLATE Chinese_PRC_CI_AS

修改数据库时,三条必须执行,如果只执行中间一句,会报错 image.png 修改Collections参考出处

批量创建数据表

这里采用C#的反射
思路:写一个空接口,什么都没有,需要创建数据表的类全部都需要继承它,然后用反射方式,获取所有继承该接口的类,然后一把全部塞InitTables里面

Models文件夹中 新建一个HModel.cs文件,添加代码

namespace uniapi.Models
{
    interface HModel { }
}

所有需要创建数据表的类都继承这个HModel接口
然后,获取所有继承HModel接口的类,塞进去

//获取所有继承IModel的非抽象类
var types = AppDomain.CurrentDomain //获取当前 Thread 的当前应用程序域。
             .GetAssemblies()
             .SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(HModel))))
             .ToArray();

//方法二:获取所有继承IModel的非抽象类
//Type[] types = Assembly
//                .GetExecutingAssembly() //获取包含当前执行的代码的程序集
//                .GetTypes()
//                .Where(x => typeof(HModel).IsAssignableFrom(x) && x.IsClass && !x.IsAbstract)//凡是继承HModel接口的非抽象类
//                .ToArray();

//设置varchar类型字段默认长度为200
db.CodeFirst.SetStringDefaultLength(200).InitTables(types);//创建数据表

如上,获取所有类,写了两种方式,实测,都可以获取到继承HModel接口的类

然后运行项目即可自动创建数据表了,不再用一个一个塞了!


到这里,基本使用上没啥大问题了