将ServiceStack.Net从4.0.39升级到4.5.6后,OrmLite模型不会填充

时间:2017-03-22 19:59:02

标签: servicestack ormlite-servicestack

将ServiceStack.Net从4.0.39升级到4.5.6后,我们看到一些未填充模型的情况,但它确实包含正确数量的记录。每条记录的属性都是默认值。恢复到4.0.39后,一切正常。

我们想知道是否需要更新某些内容?我们没有注意到文档和用法中的任何内容与示例类似。

如果答案未知,那么最简单的下一个可能的方法是找出正在发生的事情? (看起来可能需要下载源代码并编译和引用新的4.5.6 OrmLite,但有更简单的选择吗?)

  • 它适用于其他非常相似的情况(参数和表名的数量都不同)。我们没有注意到案件之间存在任何差异。工作和不工作的情况按顺序执行。更改顺序不会改变结果。
  • 在db客户端(psql)中执行sql会返回值,因此需要填充值。
  • 不会抛出任何错误。
  • 正在使用Postgres方言。

这是一个简单的例子。 https://gist.github.com/anonymous/bb514062a7d97b0ff4b0a546ef315765

using System;
using NUnit.Framework;
using ServiceStack;
using ServiceStack.Configuration;
using ServiceStack.DataAnnotations;
using ServiceStack.OrmLite;

namespace MyCompany.Tests
{
    public class OrmLiteModelArrayTests
    {
        [Alias("color")]
        public class ColorModel
        {
            public string Color { get; set; }
            public string Value { get; set; }
        }

        public class ColorJsonModel
        {
            public int Id { get; set; }
            public string ColorJson { get; set; }
        }

        [Test]
        public void test_model_with_array_to_json()
        {

            OrmLiteConfig.DialectProvider = PostgreSqlDialect.Provider;

            var testingConn = ConfigUtils.GetConnectionString("testing");

            using (var db = testingConn.OpenDbConnection())
            {
                db.DropAndCreateTable();

                db.Insert(new ColorModel { Color = "red", Value = "#f00" });
                db.Insert(new ColorModel { Color = "green", Value = "#0f0" });
                db.Insert(new ColorModel { Color = "blue", Value = "#00f" });
                db.Insert(new ColorModel { Color = "cyan", Value = "#0ff" });
                db.Insert(new ColorModel { Color = "magenta", Value = "#f0f" });
                db.Insert(new ColorModel { Color = "yellow", Value = "#ff0" });
                db.Insert(new ColorModel { Color = "black", Value = "#000" });

                const string sql = @"SELECT 1::integer AS id
                                        , json_agg(color.*) AS color_json
                                    FROM color;";

                var results = db.Select<ColorJsonModel>(sql);

                Assert.That(results.Count, Is.EqualTo(1));

                foreach (var result in results)
                {
                    Console.WriteLine("{0}".Fmt(result.ColorJson));
                    Assert.That(result.Id, Is.EqualTo(1));
                    Assert.That(result.ColorJson, Is.Not.Null);
                }

            }
        }

        [Test]
        public void test_model_with_array_and_json()
        {

            OrmLiteConfig.DialectProvider = PostgreSqlDialect.Provider;

            var testingConn = ConfigUtils.GetConnectionString("testing");

            using (var db = testingConn.OpenDbConnection())
            {
                db.DropAndCreateTable<ColorModel>();

                db.Insert(new ColorModel { Color = "red", Value = "#f00" });
                db.Insert(new ColorModel { Color = "green", Value = "#0f0" });
                db.Insert(new ColorModel { Color = "blue", Value = "#00f" });
                db.Insert(new ColorModel { Color = "cyan", Value = "#0ff" });
                db.Insert(new ColorModel { Color = "magenta", Value = "#f0f" });
                db.Insert(new ColorModel { Color = "yellow", Value = "#ff0" });
                db.Insert(new ColorModel { Color = "black", Value = "#000" });

                // SQL contains array and json aggs.
                // We usually have ARRAY fields defined in the db, but when
                // retrieved we json-ize them. In otherwords the array exists in the tables/views.
                // We use SELECT.* which would contain the ARRAY field.
                // Array fields are not used in any of our models and should not cause the other
                // fields in the model to not be populated.
                const string sql = @"SELECT 1::integer AS id
                                            , json_agg(color.*) AS color_json
                                            , array_agg(color.*) AS color_array
                                    FROM color;";

                var results = db.Select<ColorJsonModel>(sql);

                Assert.That(results.Count, Is.EqualTo(1));

                foreach (var result in results)
                {
                    Console.WriteLine("{0}".Fmt(result.ColorJson));
                    Assert.That(result.Id, Is.EqualTo(1));
                    Assert.That(result.ColorJson, Is.Not.Null);
                }

            }
        }
    }
}

更新

我们发现了一个实例,其中我们找到了一个例子,其中返回了7条记录,但是7条中的6条具有默认空值,而最后一条(第7条)记录被完全填充。

更新2:

问题是处理SELECT *中包含但未在C#模型中使用的ARRAY字段。

1 个答案:

答案 0 :(得分:2)

说明中的示例代码无法编译,但我已经使用最新版本的OrmLite测试了最接近的工作版本,以及正在按预期工作的进度:

[Alias("my_table")]
public class MyModel
{
    public int MyId { get; set; }
    public int BlahId { get; set; }
    public string Name { get; set; }
}

using (var db = OpenDbConnection())
{
    db.DropAndCreateTable<MyModel>();

    db.Insert(new MyModel { MyId = 1, BlahId = 2, Name = "foo" });
    db.Insert(new MyModel { MyId = 2, BlahId = 3, Name = "bar" });

    var results = db.GetMyModels(1, 2);

    Assert.That(results.Count, Is.EqualTo(1));
    Assert.That(results[0].MyId, Is.EqualTo(1));
    Assert.That(results[0].BlahId, Is.EqualTo(2));
    Assert.That(results[0].Name, Is.EqualTo("foo"));
}

public static class CustomSqlExtensions
{
    public static List<MyModel> GetMyModels(this IDbConnection db, int myId, int blahId)
    {
        const string sql = @"SELECT * FROM my_table WHERE my_id = @myId AND blah_id = @blahId";
        return db.Select<MyModel>(sql, new { myId, blahId });
    }
}

虽然它不会产生影响,但在使用自定义SQL时,您应该使用SqlList之类的return db.SqlList<MyModel>(sql, new { myId, blahId }); ,例如:

const string sql = @"SELECT 1::integer AS id
                            , json_agg(color.*) AS color_json
                            , array_agg(color.*) AS color_array
                    FROM color;";

var results = db.Select<ColorJsonModel>(sql);

问题Custom SQL APIs

array_agg

在Npgsql中使用未知的PostgreSQL类型

是由于Npgsql不知道GetValues()类型是什么,所以会抛出异常:

字段&#39; color_array&#39;有一个Npgsql目前不知道的类型(OID 101487)

尝试使用其GetValues()批处理API读取行数据集时。我添加了highlighted from this Gist,如果GetValues()批处理API失败,它将回退到单独的提取读取,这将解决此问题。

然而,这会引发一个不是最优的异常,您可以告诉OrmLite完全避免使用批处理OrmLiteConfig.DeoptimizeReader = true; API,告诉它始终使用单个字段提取:

this

这将避免尝试使用GetValues()并避免其异常。