Ich habe ein Objekt:
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; }
}
Wenn ich Dapper jedoch zum Aufrufen der folgenden Abfrage verwende:
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])
Ich erhalte die splitOn
, dass bei Verwendung von Multi-Mapping das splitOn
Attribut verwendet wird. Was ich bin, aber ich erhalte immer noch den Fehler. Also nehme ich an, dass ich irgendeine Art von Verwendungsfehler oder syntaxiellen Fehler habe. Der Code, der fortwährend Fehler ist, ist wie folgt:
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");
Wichtiger Hinweis: Standardmäßig verwendet Dapper ID, weshalb ich Code in Id umbenannte, aber selbst mit Code oder der Umbenennung erhalte ich immer noch einen Multi-Mapping-Fehler.
Sieht so aus, als müssten Sie nur den "Code" von splitOn entfernen: "Id, Code". Ihre Anfrage benennt sie in "Id" um.
Dapper verwendet auch "Id" als Standard, so dass keine Angabe erforderlich ist.
Dapper ist in der Lage, die zurückgegebene Zeile zu teilen, indem eine Annahme gemacht wird, dass Ihre Id-Spalten Id oder ID genannt werden. Wenn der Primärschlüssel anders ist oder Sie die Zeile an einem anderen Punkt als ID teilen möchten, verwenden Sie den optionalen Parameter splitOn.
Im Folgenden finden Sie einen kurzen Test zur Überprüfung:
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"));
}
Update auf Demo-Split nach verschiedenen Feldern und Typen
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"));
}
Ich fand den Hauptgrund heraus, warum es fehlgeschlagen ist. Dapper mochte den splitOn
Parameter nicht, der zwischen int
und string
. Indem sie alle zur Vereinheitlichung zwangen, funktionierte es. Der andere Punkt, den ich bemerkt habe, ist, dass, wenn Sie eine Spalte namens Code
, die einen Primärschlüssel spiegelt, SQL aber nicht auf einen relationalen Bezeichner gesetzt ist, dies ebenfalls einen Fehler ergibt.
Nachdem die korrigiert wurden, zog es kein Problem.