Отображение таблицы кодов в BLToolkit
В моей базе данных есть одна большая таблица "кодов" с поиском системного кода для значений, используемых во всей системе. Вот так:
[TableName("code_entries")] public class Code {
[MapField("code_nbr")][PrimaryKey, Identity] public int Id;
[MapField("code")] public string Value;
}
Я новичок в BLToolkit, и я надеюсь, что есть концепция, похожая на статические отображения, которые я видел, но которая позволит мне легко отобразить вхождения этих кодов в других таблицах в их соответствующие значения. Например:
[TableName("person")] public class Person {
[MapField("person_nbr")][PrimaryKey, Identity] public int Id;
[MapField("dob")][Nullable] public int BirthDate;
[MapField("eye_color")][Nullable] public int EyeColorCode;
[MapField("hair_color")][Nullable] public int HairColorCode;
}
Если EyeColorCode и HairColorCode, указанные выше, соответствуют значениям в таблице "Коды", могу ли я создать простой способ сопоставления этих данных в классах OR и получения всего объекта в одном запросе?
Я хотел бы в конечном итоге что-то вроде:
// person.Id = 1
// person.DOB = some date
// person.EyeColor = "Blue"
// person.HairColor = "Brown"
2 ответа
Это не совсем то, что вы хотели, но вы могли бы использовать ассоциации
так что вы можете добавить это в свой класс Person
[Association(ThisKey="eye_color", OtherKey="code_nbr", CanBeNull=true)]
public Code EyeColor;
[Association(ThisKey="hair_color", OtherKey="code_nbr", CanBeNull=true)]
public Code HairColor;
А потом сделать что-то вроде
from p in db.Person
select new
{
Id = p.Id,
DOB = p.BirthDate,
EyeColor = p.EyeColor.Value,
HairColor = p.HairColor.Value
};
В любом случае они кажутся типами кодов, которые почти никогда не меняются, я обычно помещаю их на клиент при запуске, а затем заполняю описание, когда я отображаю данные, делает все намного проще, и если я не могу найти Id, тогда я просто обновите коллекцию
Спасибо Дэвид. Я придерживался вашего подхода, но немного изменил его, чтобы он стал менее болезненным для меня. Я добавил ассоциации в мои классы, как в вашем примере:
[Association(ThisKey = "EyeColorCode", OtherKey = "Id")] public Code EyeColor { get; set; }
[Association(ThisKey = "HairColorCode", OtherKey = "Id")] public Code HairColor { get; set; }
Затем я написал метод расширения. Он принимает новый объект и объединяет все доступные для записи свойства с исходным объектом. Используя это, мне не нужно указывать каждое отдельное свойство в моем запросе, а именно:
from p in db.Person
select p.PropertyUnion(new Person() {
{
EyeColor = p.EyeColor,
HairColor = p.HairColor
};
Это экономит мне немного кода для некоторых из моих более сложных объектов, и я думаю, что он более читабелен. Вот код для метода расширения:
/// <summary>
/// Union by retrieving all non-null properties from source parameter and setting those properties on the instance object
/// </summary>
public static T PropertyUnion<T>(this T destination, T source) {
// Don't copy from a null object
if (Object.ReferenceEquals(source, null) || Object.ReferenceEquals(destination, null)) {
return destination;
}
// copy properties
foreach (var property in source.GetType().GetProperties()) {
if (!property.CanWrite || !property.CanRead)
continue;
var match = destination.GetType().GetProperty(property.Name);
if (!match.CanWrite || !match.CanRead)
throw new MethodAccessException("Matching property '" + match.Name + "' must allow both read and write operations.");
var value = property.GetValue(source, null);
if (value != null && !value.Equals(Activator.CreateInstance(property.PropertyType)))
match.SetValue(destination, value, null);
}
return destination;
}
В очередной раз благодарим за помощь!