プライベートセッターを使用するプリミティブ型のプロパティの場合Dapper
、名前がデータベース/クエリから取得したものと一致する限り、それらを自動的にマップするのに十分賢いです。
あなたのUser
クラスが集約ルートであるとしましょう
public class User : AggregateRoot
{
public int Id { get; private set; }
public string Name { get; private set; }
...
}
GetById
リポジトリからユーザーを再構築する方法があります
public class UserRepository : Repository<User>, IUserRepository
{
private UserRepository(IDbConnection dbConnection) : base(dbConnection) {}
...
public User GetById(int id)
{
const string sql = @"
SELECT *
FROM [User]
WHERE ID = @userId;
";
return base.DbConnection.QuerySingleOrDefault<User>(
sql: sql,
param: new { userId = id }
);
}
}
SQLがIdとNameの列を返す限り、それらがプライベートセッターを持っている場合でも、それらは自動的にUserクラスの一致するプロパティにマップされます。素敵できれい!
人間関係の問題
ロードする必要のある1対多のオブジェクトがある場合、すべてがトリッキーになります。
ここで、Userクラスに、 Userに属する読み取り専用の車のリストと、車の追加/削除に使用できるいくつかのメソッドがあるとします。
public class User : AggregateRoot
{
public int Id { get; private set; }
public string Name { get; private set; }
private readonly IList<Car> _cars = new List<Car>();
public IEnumerable<Car> Cars => _cars;
public void PurchaseCar(Car car)
{
_cars.Add(car);
AddEvent(new CarPurchasedByUser { ... });
}
public void SellCar(Car car)
{
_cars.Remove(car);
AddEvent(new CarSoldByUser { ... });
}
}
public class Car : Entity
{
public int Id { get; private set; }
public string Brand { get; private set; }
}
では、 Userクラスが作成されたときに、どのように車のリストをロードしますか?
複数のクエリを実行することを提案する人もいます。ユーザーを作成した後、PurchaseCar
andSellCar
メソッド(またはクラスで使用可能なメソッド)を呼び出して車を追加/削除して、車のリストを作成します。
public User GetById(int id)
{
const string sql = @"
SELECT *
FROM [User]
WHERE ID = @userId;
SELECT *
FROM [Car]
WHERE UserID = @userId;
";
using (var multi = base.DbConnection.QueryMultiple(sql, new { userId = id })
{
var user = multi.Read<User>()
.FirstOrDefault();
if (user != null)
{
var cars = multi.Read<Car>();
foreach (var car in cars)
{
user.PurchaseCar(car);
}
}
return user;
}
}
ただし、これらのメソッドには通常、他のコマンドを起動するために他のユーザーがサブスクライブする可能性のある追加のイベントが発生するため、練習している場合は実際にそうすることはできません。UserオブジェクトDomain-Driven Design
を初期化しようとしていました。
反射でそれを解決する
私のために働いた唯一のことは使用することSystem.Reflection
です!
public User GetById(int id)
{
const string sql = @"
SELECT *
FROM [User]
WHERE ID = @userId;
SELECT *
FROM [Car]
WHERE UserID = @userId;
";
using (var multi = base.DbConnection.QueryMultiple(sql, new { userId = id })
{
var user = multi.Read<User>()
.FirstOrDefault();
if (user != null)
{
var cars = multi.Read<Car>();
// Load user car list using Reflection
var privateCarListField = user.GetType()
.GetField("_cars", BindingFlags.NonPublic | BindingFlags.Instance);
privateCarListField.SetValue(car, cars);
}
return user;
}
}