将ServiceStack.Net从4.0.39升级到4.5.6后,我们看到一些未填充模型的情况,但它确实包含正确数量的记录。每条记录的属性都是默认值。恢复到4.0.39后,一切正常。
我们想知道是否需要更新某些内容?我们没有注意到文档和用法中的任何内容与示例类似。
如果答案未知,那么最简单的下一个可能的方法是找出正在发生的事情? (看起来可能需要下载源代码并编译和引用新的4.5.6 OrmLite,但有更简单的选择吗?)
这是一个简单的例子。 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字段。
答案 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);
array_agg
是由于Npgsql不知道GetValues()
类型是什么,所以会抛出异常:
字段&#39; color_array&#39;有一个Npgsql目前不知道的类型(OID 101487)
尝试使用其GetValues()
批处理API读取行数据集时。我添加了highlighted from this Gist,如果GetValues()
批处理API失败,它将回退到单独的提取读取,这将解决此问题。
然而,这会引发一个不是最优的异常,您可以告诉OrmLite完全避免使用批处理OrmLiteConfig.DeoptimizeReader = true;
API,告诉它始终使用单个字段提取:
this
这将避免尝试使用GetValues()并避免其异常。