代码之家  ›  专栏  ›  技术社区  ›  Justin Grant

Entity Framework ObjectContext->对本机DBMS的原始SQL调用

  •  4
  • Justin Grant  · 技术社区  · 15 年前

    我有一个应用程序使用ADO.NET实体框架(VS2008版本,而不是更新、更酷的版本),我需要能够调用底层DBMS(它是Postgres),以便调用实体框架不支持的某些SQL。

    有没有一种方法可以从实体框架对象上下文转到允许我执行原始SQL的内容?(我需要在插入前运行一个截断表)我同意一个黑客解决方案(例如,从ef中提取dbms的连接字符串信息,并使用该信息使用postgres ado.net提供程序创建连接),但不想管理两组连接字符串(一个用于实体框架,一个用于ado.net)。

    我知道实体框架第一版的局限性,但不值得投资将这个应用程序切换到另一个ORM,使用EF4.0也不是一个选择。

    有什么想法吗?

    顺便说一句,这个问题和 Is it possible to run native sql with entity framework? ,但该答案中描述的解决方法对我不起作用,因为我确实需要执行原始SQL。

    4 回复  |  直到 12 年前
        1
  •  17
  •   Justin Grant    15 年前

    克雷格的回答虽然不太管用,但却让我找到了正确的方向。原来有一个EntityConnection.StoreConnection属性,它可以让您连接到底层DBMS。所以执行“本机”SQL就这么简单:

        static void ExecuteSql(ObjectContext c, string sql)
        {
            var entityConnection = (System.Data.EntityClient.EntityConnection)c.Connection;
            DbConnection conn = entityConnection.StoreConnection;
    
            ConnectionState initialState = conn.State;
            try
            {
                if (initialState != ConnectionState.Open)
                    conn.Open();  // open connection if not already open
                using (DbCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.ExecuteNonQuery();
                }
            }
            finally
            {
                if (initialState != ConnectionState.Open)
                    conn.Close(); // only close connection if not initially open
            }
        }
    
        2
  •  2
  •   Craig Stuntz    15 年前

    是的,你可以这样做。查看entityConnection.storeConnection。您可以从ObjectContext获取连接。

        3
  •  0
  •   bniwredyc    15 年前

    根据 this post 实体框架v1不支持DML。

    但是有对存储过程的支持,但只有这些存储过程返回实体。这意味着,如果以这种方式创建存储过程(SQL Server语法):

    CREATE PROCEDURE [dbo].[usp_trncate]
    AS
    BEGIN
     truncate table t1
    END
    

    不能将其作为函数导入(实际上可以,但它不起作用-不会生成此函数的代码)

    我已经找到了实现目标的拐杖解决方案:如果您将sp定义为以下值:

    CREATE PROCEDURE [dbo].[usp_trncate]
    AS
    BEGIN
     truncate table t1
    
     select top 1 * from t1
    END
    

    您可以作为函数导入并在代码中使用它,如下所示:

    TestEntities context = new TestEntities();
    context.TruncateTable();
    

    (TruncateTable是导入函数的名称)

    我认为还有另一个(更好的)解决方案。挖掘的其他方法是修补.edmx文件,使sp不返回工作,或者编写另一个sp并将其映射到表插入函数(该sp必须截断表并插入行)

    我希望它能帮助你。

        4
  •  0
  •   orderedanalog    12 年前

    谢谢贾斯廷。我花了好几个小时试图弄清楚为什么实体框架连接上的storeConnection属性不可用…

    对我来说关键的一点是,您必须将您的EF连接正式转换为System.Data.EntityClient.EntityConnection:

    VaR NeNCON= (system.data.entityclient.entityconnection)数据库连接;

    一旦我这样做了,其他一切都有意义。

    推荐文章