使用Entity Framework Core获取表使用的空间

时间:2019-04-17 23:49:54

标签: entity-framework tsql entity-framework-core

我一直在使用以下T-SQL来获取数据库中表的已用空间(以兆字节为单位):

SELECT 
    t.NAME AS TableName,
    CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TotalSpaceMB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    t.Name

结果如下:

enter image description here

是否有使用EF Core执行等效操作的好方法?

我浏览了Raw SQL Queries文档,但是那里的示例似乎并不适用,因为它们主要与检索实体有关。

2 个答案:

答案 0 :(得分:1)

您可以同时使用QueryTypesRaw SQL Queries

首先,创建一个代表您的结果并封装SQL查询的类。您可以根据需要组织以下代码,但这应该可以使您理解。

    public class DatabaseTableSize
    {
        public class View
        {
            public string TableName { get; private set; }
            public decimal TableSizeMb { get; private set; }
        }

        public static async Task<List<View>> Query(YourDbContextType dbContext)
        {
            return await dbContext.DatabaseTableSizeView
                .FromSql(@"SELECT
                            t.NAME AS TableName,
                            CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TableSizeMb
                        FROM sys.tables t
                        INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
                        INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
                        INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
                        LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
                        WHERE
                            t.NAME NOT LIKE 'dt%'
                            AND t.is_ms_shipped = 0
                            AND i.OBJECT_ID > 255
                        GROUP BY
                            t.Name, s.Name, p.Rows
                        ORDER BY
                            t.Name")
                .ToListAsync();
        }
    }

然后将QueryType定义添加到您的DbContext

public DbQuery<DatabaseTableSize.View> DatabaseTableSizeView { get; set; }

然后在任何需要数据的地方调用它

var results = await DatabaseTableSize.Query(dbContext);

答案 1 :(得分:1)

我们绝对可以使用Raw SQL查询来完成这项工作。

首先,当我们运行此查询时,最好以实体框架可以使用的类类型返回结果。我曾尝试检索任意查询结果,但发现这些结果很难解析。  我的建议是创建一个类来描述您将从RawSQL查询中获得的结果。

因此,无论您在哪里为该项目存储模型(甚至在新文件中),我们都将创建一个名为SpaceCalculations的新类,并使用[NotMapped]属性对其进行修饰,以防止EF Core试图将其制成表格。

[NotMapped]
    public class SpaceCalculations
    {
        public string TableName { get; set; }
        public decimal TotalSpaceMB { get; set; }
    }

接下来,我们需要在我们的DBContext中注册该类。在您的DBContext中定义各种Dbset<Type>记录的位置,添加以下内容:

public DbQuery<SpaceCalculations> SpaceCalculations { get; set; }

最后,要检索数据本身,只需将其懒惰地放入Home \ Index控制器动作中即可。

public IActionResult Index()
        {
            List<SpaceCalculations> SpaceData = _context.SpaceCalculations.
                 FromSql(@"YOUR LONG SQL STATEMENT HERE").ToList();
            ViewBag.SpaceInfo = SpaceData;
            return View();
        }

然后,为了渲染信息,我在Index.cshtml文件中创建了以下内容。

<h2>Table Space for table ....</h2>
<table>
    <tr>
        <th>
            TableName
        </th>
        <th>
            TableSpace
        </th>
        </tr>
        @foreach (SpaceCalculations SpaceRecord in ViewBag.SpaceInfo)
        {
        <tr>
            <td>
                @SpaceRecord.TableName
            </td>
            <td>
                @SpaceRecord.TotalSpaceMB
            </td>
    </tr>
    }
</table>

还有完成的结果!

enter image description here

You can read more about this here.