小巧玲珑多映射
问题描述:
我有一个目标:小巧玲珑多映射
public class Species : IEntity<int>
{
public int Id { get; set; }
public string Name { get; set; }
public SpeciesCategory Category { get; set; }
public WetlandIndicator WetlandIndicator { get; set; }
}
public class SpeciesCategory : IEntity<int>
{
public int Id { get; set; }
public string Name { get; set; }
}
public class WetlandIndicator : IEntity<string>
{
public string Id { get; set; }
public string Designation { get; set; }
public bool Status { get; set; }
}
然而,当我用小巧玲珑来调用下面的查询:
SELECT
[Species].*,
[SpeciesType].*,
[WetlandIndicator].Code AS Id,
[WetlandIndicator].Designation
FROM
((([Watershed].[Vegetation].[Species] INNER JOIN [Vegetation].[SpeciesCategory]
ON [Watershed].[Vegetation].[Species].[SpeciesCategoryId] = [Vegetation].[SpeciesCategory].[Id]) INNER JOIN [Watershed].[Vegetation].[SpeciesType]
ON [Watershed].[Vegetation].[Species].[SpeciesTypeId] = [Vegetation].[SpeciesType].[Id]) INNER JOIN [Watershed].[Vegetation].[WetlandIndicator]
ON [Vegetation].[Species].[WetlandIndicatorCode] = [Vegetation].[WetlandIndicator].[Code])
我收到使用多映射时确保,请确保您使用splitOn
属性。我是谁,但我仍然收到错误。所以我假设我有一些类型的使用错误或合成文本错误。 ,不断的错误是因为代码如下:
public async Task<IEnumerable<SpeciesDomain>> GetAllSpecies(string query) =>
await dbConnection.QueryAsync<Species, SpeciesCategory, WetlandIndicator, SpeciesDomain>(query, (species, speciesCategory, wetlandIndicator) =>
{
species.SpeciesCategory = speciesCategory;
species.WetlandIndicator = wetlandIndicator;
return species;
}, splitOn: "Id, Code");
重要提示:默认情况下小巧玲珑利用标识,这就是为什么我改名守则ID,但即使有代码或重命名我仍然收到了多映射错误。
答
看起来你只需要从splitOn中删除'代码':“Id,Code”。您的查询将其重命名为“Id”。
Dapper还使用“Id”作为默认值,因此不需要指定。
Dapper能够通过假设 您的Id列被命名为Id或id来拆分返回的行。如果您的主键不同于 或者您想要在除Id以外的其他位置拆分该行,请使用 可选splitOn参数。
下面是一个快速测试来验证:
using (var conn = new SqlConnection(@"Data Source=.\sqlexpress;Integrated Security=true; Initial Catalog=foo"))
{
var result = conn.Query<Species, SpeciesCategory, WetlandIndicator, Species>(
"select Id = 11, Name = 'Foo', Id = 22, Name = 'Bar', Id = 33, Designation = 'House Cat' ",
(species, speciesCategory, wetlandIndicator) =>
{
species.Category = speciesCategory;
species.WetlandIndicator = wetlandIndicator;
return species;
}).First();
Assert.That(result.Id, Is.EqualTo(11));
Assert.That(result.Category.Id, Is.EqualTo(22));
Assert.That(result.Category.Name, Is.EqualTo("Bar"));
Assert.That(result.WetlandIndicator.Id, Is.EqualTo(33));
Assert.That(result.WetlandIndicator.Designation, Is.EqualTo("House Cat"));
}
更新演示不同领域和类型
public class Species
{
public int Id { get; set; }
public string Name { get; set; }
public SpeciesCategory Category { get; set; }
public WetlandIndicator WetlandIndicator { get; set; }
}
public class SpeciesCategory
{
public int Id { get; set; }
public string Name { get; set; }
}
public class WetlandIndicator
{
public string Code { get; set; }
public string Designation { get; set; }
public bool Status { get; set; }
}
using (var conn = new SqlConnection(@"Data Source=.\sqlexpress;Integrated Security=true; Initial Catalog=foo"))
{
var result = conn.Query<Species, SpeciesCategory, WetlandIndicator, Species>(
"select Id = 11, Name = 'Foo', Id = 22, Name = 'Bar', Code = 'X', Designation = 'House Cat' ",
(species, speciesCategory, wetlandIndicator) =>
{
species.Category = speciesCategory;
species.WetlandIndicator = wetlandIndicator;
return species;
}, splitOn: "Id, Code").First();
Assert.That(result.Id, Is.EqualTo(11));
Assert.That(result.Category.Id, Is.EqualTo(22));
Assert.That(result.Category.Name, Is.EqualTo("Bar"));
Assert.That(result.WetlandIndicator.Code, Is.EqualTo("X"));
Assert.That(result.WetlandIndicator.Designation, Is.EqualTo("House Cat"));
}
答
分裂所以,我发现它失败的主要原因。 Dapper不喜欢splitOn
参数在int
和string
之间交替。通过迫使他们统一起来,它就起作用了。我注意到的另一个项目是,如果你有一个名为Code
的列,例如镜像一个主键但SQL没有设置为关系标识符,它也会出错。
经过纠正后,没有问题。
只是为了澄清他人:如果您使用不同数据类型的字段进行拆分,Dapper不会失败。我会更新我的演示答案。 –
我需要澄清,如果你有字段:'代码'和一个名为'代码'问题的Id列。 – Greg