我可以使用ServiceStack OrmLite生成SQL脚本吗?

时间:2014-05-05 19:45:52

标签: ormlite-servicestack

是否可以使用OrmLite生成SQL脚本而不对数据库执行它?我想从一个实时的SqlServer数据库加载一个DTO列表,并输出一个脚本来删除和插入每个记录。

提供的迷你探查器支持日志记录,但看起来需要包装真实的数据库连接。

3 个答案:

答案 0 :(得分:1)

直接使用DialectProvider似乎可以满足我的需求。 ToInsertRowStatement采用IDbCommand参数,但不使用null

OrmLiteConfig.DialectProvider = SqlServerOrmLiteDialectProvider.Instance;
var dto = new PersonDTO { Id = Guid.NewGuid(), Name = "Carl" };
var deleteText = SqlServerOrmLiteDialectProvider.Instance.ToDeleteRowStatement(dto);
var insertText = SqlServerOrmLiteDialectProvider.Instance.ToInsertRowStatement((IDbCommand)null, dto);

有更好的选择吗?

答案 1 :(得分:1)

现在OrmLite extension methods are now mockable提供您自己的OrmLiteResultsFilter,这是微不足道的。

E.g。下面的ResultsFilter记录每个执行的sql语句,并将OrmLiteResultsFilter中的行为设置为inmlite返回空结果:

public class CaptureSqlFilter : OrmLiteResultsFilter
{
    public CaptureSqlFilter()
    {
        SqlCommandFilter = CaptureSqlCommand;
        SqlCommandHistory = new List<SqlCommandDetails>();
    }

    private void CaptureSqlCommand(IDbCommand command)
    {
        SqlCommandHistory.Add(new SqlCommandDetails(command));
    }

    public List<SqlCommandDetails> SqlCommandHistory { get; set; }

    public List<string> SqlStatements
    {
        get { return SqlCommandHistory.Map(x => x.Sql); }
    }
}

您可以将其包装在使用范围内以捕获每个SQL语句而不执行它们,例如:

using (var captured = new CaptureSqlFilter())
using (var db = OpenDbConnection())
{
    db.CreateTable<Person>();
    db.Select<Person>(x => x.Age > 40);
    db.Single<Person>(x => x.Age == 42);
    db.Count<Person>(x => x.Age < 50);
    db.Insert(new Person { Id = 7, FirstName = "Amy", LastName = "Winehouse" });
    db.Update(new Person { Id = 1, FirstName = "Jimi", LastName = "Hendrix" });
    db.Delete<Person>(new { FirstName = "Jimi", Age = 27 });
    db.SqlColumn<string>("SELECT LastName FROM Person WHERE Age < @age", 
        new { age = 50 });
    db.SqlList<Person>("exec sp_name @firstName, @age", 
        new { firstName = "aName", age = 1 });
    db.ExecuteNonQuery("UPDATE Person SET LastName={0} WHERE Id={1}"
        .SqlFmt("WaterHouse", 7));

    var sql = string.Join(";\n\n", captured.SqlStatements.ToArray());
    sql.Print();
}

打印出来:

CREATE TABLE "Person" 
(
  "Id" INTEGER PRIMARY KEY, 
  "FirstName" VARCHAR(8000) NULL, 
  "LastName" VARCHAR(8000) NULL, 
  "Age" INTEGER NOT NULL 
); 
;

SELECT "Id", "FirstName", "LastName", "Age" 
FROM "Person"
WHERE ("Age" > 40);

SELECT "Id", "FirstName", "LastName", "Age" 
FROM "Person"
WHERE ("Age" = 42)
LIMIT 1;

SELECT COUNT(*) FROM "Person" WHERE ("Age" < 50);

INSERT INTO "Person" ("Id","FirstName","LastName","Age") VALUES (@Id,@FirstName,@LastName,@Age);

UPDATE "Person" SET "FirstName"=@FirstName, "LastName"=@LastName, "Age"=@Age WHERE "Id"=@Id;

DELETE FROM "Person" WHERE "FirstName"=@FirstName AND "Age"=@Age;

SELECT LastName FROM Person WHERE Age < @age;

exec sp_name @firstName, @age;

UPDATE Person SET LastName='WaterHouse' WHERE Id=7

CaptureSqlFilterTests.cs

中提供了更多示例

由于CaptureSqlFilter很有用,我刚刚将其添加到OrmLite in this commit,它将位于下一个 v4.0.20 中,现在是available on MyGet

答案 2 :(得分:1)

我用这个来捕捉声明并继续运行声明。

    public class CustomOrmLiteExecFilter : OrmLiteExecFilter
{
    public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter)
    {
        var holdProvider = OrmLiteConfig.DialectProvider;
        var dbCmd = CreateCommand(dbConn);
        try
        {
            var ret = filter(dbCmd);

            var pureSQL = holdProvider.MergeParamsIntoSql(dbCmd.CommandText, dbCmd.Parameters.OfType<IDbDataParameter>());
            //log or save the SQL Statement


            return ret;
        }
        finally
        {
            if (OrmLiteConfig.DialectProvider != holdProvider)
                OrmLiteConfig.DialectProvider = holdProvider;
        }
    }
}

和用法:

 OrmLiteConfig.ExecFilter = new CustomOrmLiteExecFilter();

希望这可以帮到你!