实体框架OnModelCreating - 检查缺少的DB对象

时间:2016-02-25 14:35:58

标签: c# sql-server entity-framework

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

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

,因此访问用户数据的唯一方法是使用相应的视图ENTRIES_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身份验证,使用Annotations实现对象映射。
我不知道的是,如果此表存在,在尝试Entity().ToTable(...)之前如何检查。如果它没有,我想调用存储过程,为用户创建一个新视图。
我已经尝试将ToTable - 调用放在try-catch中,但即使它无法正常连接,也不会导致异常。

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

编辑:我决定用查询手动检查应该没问题,如果没有&#34;清洁&#34;解。有没有办法在OnModelCreating中获取服务器连接,还是我必须自己创建一个?

1 个答案:

答案 0 :(得分:0)

我设法让这个工作,但只有自己的连接。我无法使用现有的,因为DbContext阻止我在OnModelCreating中访问它。

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");
}