je la classe suivante que je suis en train d'hydrater à:Dapper - Gestion de cartographie personnalisée pour l'entité ddd avec des champs en lecture seule par le constructeur
public class Product
{
public readonly Sku Sku;
public string Name { get; private set; }
public string Description { get; private set; }
public bool IsArchived { get; private set; }
public Product(Sku sku, string name, string description, bool isArchived)
{
Sku = sku;
Name = name;
Description = description;
IsArchived = isArchived;
}
}
qui utilise les classes ci-dessous qui mettent en œuvre les concepts de mon entité DDD modèle de domaine (code non pertinent enlevé pour conserver le code court, mis en lecture seule pour rendre immuable une fois construit):
public class Sku
{
public readonly VendorId VendorId;
public readonly string SkuValue;
public Sku(VendorId vendorId, string skuValue)
{
VendorId = vendorId;
SkuValue = skuValue;
}
}
public class VendorId
{
public readonly string VendorShortname;
public VendorId(string vendorShortname)
{
VendorShortname = vendorShortname;
}
}
J'essaie et exécuter la requête paramétrées qui hydrate pour un objet produit:
using (connection)
{
connection.Open();
return connection.QueryFirst<Product>(ReadQuery, new { VendorId = sku.VendorId.VendorShortname, SkuValue = sku.SkuValue });
}
Il jette l'exception suivante car il ne sait pas comment traiter avec le type Sku
dans le constructeur:
System.InvalidOperationException: « Un constructeur par défaut parameterless ou une signature correspondant (système. chaîne VendorId, System.String SkuValue, Nom System.String, description System.String, System.UInt64 IsArchived) est nécessaire pour Domain.Model.Products.Product matérialisation »
J'ai regardé en utilisant un SqlMapper.TypeHandler<Product>
personnalisé mais le Parse(object value)
passe seulement jamais dans une seule valeur analysée de la colonne de base de données VendorId
(si elle a passé dans un tableau de valeurs ici, je pourrais faire la cartographie moi-même).
est-il un moyen de personnaliser la gestion de l'objet afin que je puisse passer tous les paramètres au constructeur comme ci-dessous:
using (connection)
{
var command = connection.CreateCommand();
command.CommandText = "SELECT VendorShortname, SkuValue, Name, Description, IsArchived FROM Products WHERE [email protected] AND [email protected]";
command.Parameters.AddWithValue("@VendorShortname", sku.VendorId.VendorShortname);
command.Parameters.AddWithValue("@SkuValue", sku.SkuValue);
connection.Open();
var reader = command.ExecuteReader();
if (reader.HasRows==false)
return null;
reader.Read();
return new Product(
new Sku(new VendorId(reader.GetString("VendorId")),reader.GetString("SkuValue")),
reader.GetString("Name"),
reader.GetString("Description"),
reader.GetBoolean("IsArchived"));
}
Je suppose que je pourrais créer un constructeur spécifique avec Product(string VendorShortname, string SkuValue, string Name, string Description, UInt64 IsArchived)
mais je préférerait (doit) avoir cette préoccupation dans le code de mappage plutôt que dans mon modèle de domaine.
En passant par-dessus un pseudo-code, ce que je pourrais faire est de lancer mon propre ORM, mais je voudrais plutôt faire similaire via Dapper.
- Obtenir tous les constructeurs pour objet par réflexion
- Si des paramètres dans le constructeur est un type, obtenez ses constructeurs
- Pour chaque constructeur (y compris les paramètres), mapper le nom du constructeur à la colonne de lecteur SQL (et Type)
Cela équivaudrait à VendorShortname
utilisé pour VendorId(string vendorShortname)
et Name
, Description
, isArchived
utilisé pour Product(Sku sku, string name, string description, bool isArchived)
publique ... quelque chose est Simi lièrement fait par MongoDB selon ma réponse affichée à l'adresse suivante, un équivalent de cartographie manuelle Dapper serait génial MongoDB Composite Key: InvalidOperationException: {document}.Identity is not supported
'mais je préfère (doit) avoir cette préoccupation dans le code de mappage plutôt que dans mon modèle de domaine. Pouvez-vous nous parler pourquoi vous ** devez ** l'avoir comme ça? – mjwills
Je n'ai pas de problèmes de persistance dans mon modèle de domaine pour d'autres référentiels (MongoDB). Si possible, je voudrais utiliser SQL/Dapper pour garder les choses plus simples. Mettra à jour mon message sur ce qui devrait être fait, pourrait rouler le mien, mais je ne veux pas réinventer la roue, ni écrire du code aussi bon que – g18c