本文介绍了如何正确地“单数化”? Dapper.Contrib创建表格名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个.Net Core 3.1 Console应用程序。

I have a .Net Core 3.1 Console application.

在SQL Server数据库中,我的表具有唯一名称,与POCO类相同,这对于

In SQL Server database I have tables with singular names, the same as my POCO classes, which is convenient for matching and maintaining.

对于插入,更新和删除操作,我想使用 Dapper.Contrib 库。但是,当我运行插入功能Dapper在生成的SQL查询中将表名复数时。

For Insert, Update and Delete operations I want to use Dapper.Contrib library. But when I run Insert function Dapper pluralize table names in generated SQL queries.

SQL表 Student:

SQL table "Student":

CREATE TABLE Student
    StudentId int NOT NULL PRIMARY KEY,
    FirstName varchar(50),
    LastName varchar(50)

C#代码

public class Student
{
    public int StudentId {get; set;}
    public string FirstName {get; set;}
    public string LastName {get; set;}
}


class Program
{
    static void Main(string[] args)
    {
        var students = new List<Student>()
            {
                new Student { StudentId = 1, FirstName = "John", LastName = "Doe"},
                new Student { StudentId = 2, FirstName = "Tony", LastName = "Montana"}
            }

        long result;
        using (var cn = new SqlConnection(connString))
            {
                        result = cn.Insert(students);
            }
    }
}

在输出时我得到一个例外:

On output I get an exception:

我四处寻找解决方案,但找不到有效的示例。通常,有两种建议:

I surfed around to find a solution, but couldn't find a working example. In general there two kinds of recommendations:


  1. 使用数据注释。这个不适合我,因为使用 Scaffold-DbContext 从数据库自动创建了许多POCO对象。在开发过程中,我对数据库进行了更改,然后再次重新创建了POCO。此操作将删除对生成的POCO类所做的所有更改。

  1. Use data annotations. This one is not suitable for me, as there are a lot of POCO objects created automatically from a database using Scaffold-DbContext. During the development process, I make changes in database and then re-create POCOs again. This operation deletes all changes made in generated POCO classes.

使用 SqlMapperExtensions 委托:

SqlMapperExtensions.TableNameMapper =(type)=> {
// //在此处执行某些操作以使类型
的名称返回类型type.Name;。
};

我不知道如何正确使用此功能代表,以及放置在哪里。
我尝试了一段时间,但是我确定我没有正确使用它:

I don't know how to properly use this delegate, and where to place it.I experimented a while, but I am sure that I don't use it properly:

using (var cn = new SqlConnection(connString))
    {
            SqlMapperExtensions.TableNameMapper = (type) =>
            {
                type.Name.Remove(type.Name.Length - 1, 1);
                return type.Name;
            };
            result = cn.Insert(students);
    }

在这行代码 type.Name.Remove (type.Name.Length-1,1); 我试图实现一个函数,该函数可以切断类型为 Student ,假设Dapper将最后一个字母 s添加到类的名称,然后在实现中将其删除。
示例: Student =>学生=>学生=>学生

On this line of code type.Name.Remove(type.Name.Length - 1, 1); I tried to implement a function which cuts-off the last letter in the name of the type Student, assuming that Dapper adds the last letter "s" to the name of the class, and I remove it in my implementation.Example: Student => Students => Student(s) => Student.

长话短说-我找不到如何实现将表名单数化的函数的解决方案。

Long story short - I couldn't find a solution of how to implement a function that will "singularize" my table names.

我应该如何使用 SqlMapperExtensions ,或者还有另一种方法可以单数化表名而无需进行更改POCO类?

How should I use SqlMapperExtensions or maybe there is another approach which may "singularize" table names without making changes in POCO classes?

推荐答案

您的实现存在两个问题,但由于您实际上返回的是 type .Name ,它应该返回您类型的名称(在本例中为 Student )。

Your implementation has a couple of problems but, because you're essentially returning type.Name, it should be returning the name of your type (in this case Student).

首先让我们解决当前 TableNameMapper 实现的问题;

First let's address the problems with your current implementation of TableNameMapper;


  1. 您只需要设置一次委托。您可以在 Startup 类的 ConfigureServices 之类的地方执行此操作。现在,您每次打开连接时都要进行设置。

  1. You only need to set the delegate once. You can do this somewhere like the ConfigureServices of your Startup class. Right now you're setting it everytime you open your connection.

您的实现会执行 type.Name.Remove(type.Name。长度-1,1); ,但您没有将运算结果分配给变量。即使分配了结果,您仍然只返回 type.Name

Your implementation executes type.Name.Remove(type.Name.Length - 1, 1); but you're not assigning the result of the operation to a variable. Even if you had assigned the result you're just returning type.Name anyway.

我运行了上面的代码,并且在LINQPad中对我而言正确运行。我建议在代理的 return type.Name; 行上的调试器中添加一个断点。如果您需要手动调试,请查看。检查实际上是什么 type.Name 并从那里去。

I ran the code you have above and it works correctly for me in LINQPad. I'd suggest adding a breakpoint in your debugger on the return type.Name; line of your delegate. If you need a hand debugging then take a look at the Visual Studio debugging documentation. Check what type.Name actually is and go from there.

这是我逐字记录的代码:

Here's the code I ran verbatim:

public class Student
{
    public int StudentId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Program
{
    static void Main()
    {
        SqlMapperExtensions.TableNameMapper = (type) => type.Name;

        var students = new List<Student>
        {
            new Student { StudentId = 1, FirstName = "John", LastName = "Doe" },
            new Student { StudentId = 2, FirstName = "Tony", LastName = "Montana" }
        };

        using (var sqlConnection = new SqlConnection(connectionString))
        {
            sqlConnection.Insert(students);
        }
    }
}

这篇关于如何正确地“单数化”? Dapper.Contrib创建表格名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-13 13:56