实体框架模型创建 - 检查缺少的数据库对象

本文关键字:数据库 对象 检查 框架 模型 创建 实体 | 更新日期: 2023-09-27 18:36:08

我目前正在设置一个系统,其中SQL服务器到客户端连接的基本服务器端安全性是通过每个用户的视图(Windows身份验证)实现的。
保存所有数据的主表Entries

DENY SELECT, UPDATE, INSERT, DELETE ON [dbo].[Entries] FOR public

,因此访问用户数据的唯一方法是使用其相应的视图ENTRIES_USER("User"是一个占位符),它显式获得

GRANT SELECT, INSERT, UPDATE, DELETE ON [dbo].[Entries_USER] TO [DOMAIN'user]

.此外,public的默认权限也会减少,因此没有其他人可以从视图中读取。到目前为止一切正常,现在来了很酷的东西。


我使用实体框架和"CodeFirst"(它在现有数据库上,但映射在运行时发生)连接到此数据库,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Entry>().ToTable("Entries_" + Environment.UserName.ToUpper());
    modelBuilder.Entity<Project>().ToTable("Projects");
}

连接字符串启用 Windows 身份验证,对象映射通过注释实现。
我不知道的是,在尝试Entity().ToTable(...)这个表是否存在之前如何检查。如果没有,我想调用一个存储过程,为 user.
创建一个新视图我已经尝试将ToTable -Call 放入 try-catch 中,但即使它无法正确连接,这也不会导致异常。

有没有办法在不使用硬编码 SQL 查询的情况下提前检查我要映射到的表/视图是否已经存在?如果没有,当 EF 映射失败时,我是否可以以某种方式做出反应,执行一些操作(存储过程调用),然后重试?

编辑:如果没有"干净"的解决方案,我决定手动检查查询应该没问题。有没有办法在OnModelCreating中获取服务器连接,还是我必须自己创建一个?

实体框架模型创建 - 检查缺少的数据库对象

我设法让它工作,但只能通过自己的连接。我不能使用现有的,因为 DbContext 阻止我在 OnModelCreation 中访问它。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    string viewname = "Entries_" + Environment.UserName.ToUpper();
    using (SqlConnection connection = new SqlConnection())
    using (SqlCommand initCmd = new SqlCommand("IF NOT EXISTS(select * FROM sys.views where name = @ViewName) exec dbo.spAddUser @User, @Domain", connection))
    {
        // the connection string is the same one I use to create the DbContext
        connection.ConnectionString = ConfigurationManager.ConnectionStrings["AppConnectionString"].ConnectionString;
        initCmd.Parameters.AddWithValue("ViewName", viewname);
        initCmd.Parameters.AddWithValue("User", Environment.UserName);
        initCmd.Parameters.AddWithValue("Domain", GetDomain());            
        try
        {
            connection.Open();
            initCmd.ExecuteNonQuery();
        }
        catch (SqlException e)
        {
            Debug.WriteLine(e.Message);
            // TODO
        }
    }
    modelBuilder.Entity<Entry>().ToTable(viewname);
    modelBuilder.Entity<Project>().ToTable("Projects");
}