如何为实体框架创建的 SQL 语句获得更好的表别名?

cre*_*mor 5 .net entity-framework entity-framework-6.1

是否可以控制 Entity Framework 为其创建的 SQL 语句使用哪些表别名?例如,代替

SELECT [Extent1].[Id] AS [Id]
FROM [dbo].[Orders] AS [Extend1]
INNER JOIN [dbo].[Customers] AS [Extend2] ON [Extend1].[CustomerId] = [Extend2].[Id]
WHERE [Extent2].[Name] = 'xyz'
Run Code Online (Sandbox Code Playgroud)

我想得到

SELECT [order].[Id] AS [Id]
FROM [dbo].[Orders] AS [order]
INNER JOIN [dbo].[Customers] AS [customer] ON [order].[CustomerId] = [customer].[Id]
WHERE [customer].[Name] = 'xyz'
Run Code Online (Sandbox Code Playgroud)

或类似的东西,只要我不必记住哪个扩展数是哪个表。当然,在这个简单的示例中它没有问题,但是在您必须[Extend1]进行的查询中,[Extend7]它确实变得复杂了。

Yul*_*dra 3

你可以使用IDbCommandInterceptor并覆盖CommandText.

我刚刚创建了一个非常简单的逻辑来使用正则表达式替换别名。

以下代码

var query = (from f1 in db.Foos
            where f1.ParentFooId == null
            join f2 in db.Foos on f1.FooId equals f2.ParentFooId
            select f2).ToArray();
Run Code Online (Sandbox Code Playgroud)

默认情况下会变成类似的东西

SELECT 
    [Extent1].[FooId] AS [FooId], 
    [Extent2].[FooId] AS [FooId1], 
    [Extent2].[FooName] AS [FooName], 
    [Extent2].[ParentFooId] AS [ParentFooId], 
    [Extent2].[ParentFoo_FooId] AS [ParentFoo_FooId]
    FROM  [dbo].[Foos] AS [Extent1]
    INNER JOIN [dbo].[Foos] AS [Extent2] ON [Extent1].[FooId] = [Extent2].[ParentFooId]
    WHERE [Extent1].[ParentFooId] IS NULL
go
Run Code Online (Sandbox Code Playgroud)

然后我截获了命令文本ReaderExcecuting

public void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
    var aliasLookup = new Dictionary<string, string>();
    var tableLookup = new Dictionary<string, int>();

    var text = command.CommandText;
    // Looking something like "[dbo].[Foos] AS [Extent1]"
    var pattern = @"\[dbo\]\.\[([\w\d]*)\] AS \[(Extent\d*)\]";
    var matches = Regex.Matches(text, pattern);
    foreach(Match m in matches)
    {
        if (m.Groups.Count == 3)
        {
            var tableName = m.Groups[1].Value;
            var aliasName = m.Groups[2].Value;

            var replacement = tableName;
            if (tableLookup.ContainsKey(tableName)) replacement += tableLookup[tableName]++;
            else tableLookup.Add(tableName, 2);

            aliasLookup.Add(aliasName, replacement);
        }
    });

    foreach(var pair in aliasLookup)
    {
        var oldAliasName = string.Format("[{0}]", pair.Key);
        var newAliasName = string.Format("[{0}]", pair.Value);
        command.CommandText = command.CommandText.Replace(oldAliasName, newAliasName);
    }
}
Run Code Online (Sandbox Code Playgroud)

结果看起来像

SELECT 
    [Foos].[FooId] AS [FooId], 
    [Foos2].[FooId] AS [FooId1], 
    [Foos2].[FooName] AS [FooName], 
    [Foos2].[ParentFooId] AS [ParentFooId], 
    [Foos2].[ParentFoo_FooId] AS [ParentFoo_FooId]
    FROM  [dbo].[Foos] AS [Foos]
    INNER JOIN [dbo].[Foos] AS [Foos2] ON [Foos].[FooId] = [Foos2].[ParentFooId]
    WHERE [Foos].[ParentFooId] IS NULL
go
Run Code Online (Sandbox Code Playgroud)

这只是让您了解如何执行此操作,该逻辑尚未针对复杂查询进行测试,它应该仅用于调试。