Entity Framework,为多层层次结构的简单迭代和通用引用设置
Entity Framework, Setup for easy iteration and generic referencing of multi-level hierarchy
我有一个 entity framework 模型设置如下:
-TblProject
--TblLine
---TblGroup
----TblStation
-----TblDevice
------TblSubDevice
-------TblSubSubDevice
这些 class 中的每一个都实现了一个包含 ID、名称和类型属性的 BaseTable。我可以将我的任何实体转换为 BaseTable 并访问这些属性。
我有这样一种情况,我一直不得不编写重复的代码,因为每个 class 都是不同的类型,例如,请参阅此排序函数:
public static void OrderTreeSetup(ObservableCollection<tblProject> Table, System.ComponentModel.ListSortDirection direction)
{
ICollectionView ParentTable = CollectionViewSource.GetDefaultView(Table);
ParentTable.SortDescriptions.Clear();
ParentTable.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblProject Project in Table)
{
ICollectionView Projects = CollectionViewSource.GetDefaultView(Project.tblLines);
Projects.SortDescriptions.Clear();
Projects.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblLine Line in Project.tblLines)
{
ICollectionView Lines = CollectionViewSource.GetDefaultView(Line.tblGroups);
Lines.SortDescriptions.Clear();
Lines.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblGroup Group in Line.tblGroups)
{
ICollectionView Groups = CollectionViewSource.GetDefaultView(Group.tblStations);
Groups.SortDescriptions.Clear();
Groups.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblStation Station in Group.tblStations)
{
ICollectionView Stations = CollectionViewSource.GetDefaultView(Station.tblDevices);
Stations.SortDescriptions.Clear();
Stations.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblDevice Device in Station.tblDevices)
{
ICollectionView Devices = CollectionViewSource.GetDefaultView(Device.tblSubDevices);
Devices.SortDescriptions.Clear();
Devices.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblSubDevice SubDevice in Device.tblSubDevices)
{
ICollectionView SubDevices = CollectionViewSource.GetDefaultView(SubDevice.tblSubSubDevices);
SubDevices.SortDescriptions.Clear();
SubDevices.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
}
}
}
}
}
}
}
如何更改我的 entity framework 模型以提供更通用的编程方法?
您的代码确实有优化的空间(正如您看到这么多重复代码时所期望的那样)。这甚至可以用相对较少的努力完成。
让我们从容易实现的目标开始:由于 CollectionViewSource.GetDefaultView
接受类型为 object
的参数,您可以替换您的初始化代码...
ICollectionView ParentTable = CollectionViewSource.GetDefaultView(Table);
ParentTable.SortDescriptions.Clear();
ParentTable.SortDescriptions
.Add(new System.ComponentModel.SortDescription("Name", direction));
...调用此方法:
private static void ConfigureSorting(object entity, ListSortDirection direction)
{
ICollectionView view = CollectionViewSource.GetDefaultView(entity);
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription("Name", direction));
}
这将使您的初始化代码看起来更清晰,并避免代码重复部分的维护问题:
public static void OrderTreeSetup(ObservableCollection<tblProject> table,
ListSortDirection direction)
{
ConfigureSorting(table, direction);
foreach (tblProject project in table)
{
ConfigureSorting(project.tblLines, direction);
foreach (tblLine line in project.tblLines)
{
//...etc...
}
}
}
但这不是该行的结尾。由于您可以将接口应用于生成的(如果是数据库或模型优先)或自写的(如果是代码优先)POCO,您可以创建一个允许递归配置对象的接口:
interface ICascadingSetup
{
IEnumerable<object> Children { get; }
}
您可以将此接口应用于所有具有允许设置的子项的 POCO(即所有 除了 TblSubSubDevice
):
partial class TblProject : ICascadingSetup
{
IEnumerable<object> ICascadingSetup.Children => tblLines;
}
//...etc...
现在你可以引入一个递归方法来进行初始化:
public static void OrderTreeSetup(ObservableCollection<tblProject> table,
ListSortDirection direction)
{
ConfigureSortingRecursive(table, direction);
//...all further initializations you need to do...
}
private static void ConfigureSortingRecursive(IEnumerable<object> entities,
ListSortDirection direction)
{
ICollectionView view = CollectionViewSource.GetDefaultView(entities);
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription("Name", direction));
foreach (object entity in entities) {
if (entity is ICascadingSetup cascadingSetup) {
ConfigureSortingRecursive(cascadingSetup.Children, direction);
}
}
}
每当你有类似对象的这种树状表示时,总是值得检查递归是否是简化事情的一种选择。
我有一个 entity framework 模型设置如下:
-TblProject
--TblLine
---TblGroup
----TblStation
-----TblDevice
------TblSubDevice
-------TblSubSubDevice
这些 class 中的每一个都实现了一个包含 ID、名称和类型属性的 BaseTable。我可以将我的任何实体转换为 BaseTable 并访问这些属性。
我有这样一种情况,我一直不得不编写重复的代码,因为每个 class 都是不同的类型,例如,请参阅此排序函数:
public static void OrderTreeSetup(ObservableCollection<tblProject> Table, System.ComponentModel.ListSortDirection direction)
{
ICollectionView ParentTable = CollectionViewSource.GetDefaultView(Table);
ParentTable.SortDescriptions.Clear();
ParentTable.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblProject Project in Table)
{
ICollectionView Projects = CollectionViewSource.GetDefaultView(Project.tblLines);
Projects.SortDescriptions.Clear();
Projects.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblLine Line in Project.tblLines)
{
ICollectionView Lines = CollectionViewSource.GetDefaultView(Line.tblGroups);
Lines.SortDescriptions.Clear();
Lines.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblGroup Group in Line.tblGroups)
{
ICollectionView Groups = CollectionViewSource.GetDefaultView(Group.tblStations);
Groups.SortDescriptions.Clear();
Groups.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblStation Station in Group.tblStations)
{
ICollectionView Stations = CollectionViewSource.GetDefaultView(Station.tblDevices);
Stations.SortDescriptions.Clear();
Stations.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblDevice Device in Station.tblDevices)
{
ICollectionView Devices = CollectionViewSource.GetDefaultView(Device.tblSubDevices);
Devices.SortDescriptions.Clear();
Devices.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
foreach (tblSubDevice SubDevice in Device.tblSubDevices)
{
ICollectionView SubDevices = CollectionViewSource.GetDefaultView(SubDevice.tblSubSubDevices);
SubDevices.SortDescriptions.Clear();
SubDevices.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", direction));
}
}
}
}
}
}
}
如何更改我的 entity framework 模型以提供更通用的编程方法?
您的代码确实有优化的空间(正如您看到这么多重复代码时所期望的那样)。这甚至可以用相对较少的努力完成。
让我们从容易实现的目标开始:由于 CollectionViewSource.GetDefaultView
接受类型为 object
的参数,您可以替换您的初始化代码...
ICollectionView ParentTable = CollectionViewSource.GetDefaultView(Table);
ParentTable.SortDescriptions.Clear();
ParentTable.SortDescriptions
.Add(new System.ComponentModel.SortDescription("Name", direction));
...调用此方法:
private static void ConfigureSorting(object entity, ListSortDirection direction)
{
ICollectionView view = CollectionViewSource.GetDefaultView(entity);
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription("Name", direction));
}
这将使您的初始化代码看起来更清晰,并避免代码重复部分的维护问题:
public static void OrderTreeSetup(ObservableCollection<tblProject> table,
ListSortDirection direction)
{
ConfigureSorting(table, direction);
foreach (tblProject project in table)
{
ConfigureSorting(project.tblLines, direction);
foreach (tblLine line in project.tblLines)
{
//...etc...
}
}
}
但这不是该行的结尾。由于您可以将接口应用于生成的(如果是数据库或模型优先)或自写的(如果是代码优先)POCO,您可以创建一个允许递归配置对象的接口:
interface ICascadingSetup
{
IEnumerable<object> Children { get; }
}
您可以将此接口应用于所有具有允许设置的子项的 POCO(即所有 除了 TblSubSubDevice
):
partial class TblProject : ICascadingSetup
{
IEnumerable<object> ICascadingSetup.Children => tblLines;
}
//...etc...
现在你可以引入一个递归方法来进行初始化:
public static void OrderTreeSetup(ObservableCollection<tblProject> table,
ListSortDirection direction)
{
ConfigureSortingRecursive(table, direction);
//...all further initializations you need to do...
}
private static void ConfigureSortingRecursive(IEnumerable<object> entities,
ListSortDirection direction)
{
ICollectionView view = CollectionViewSource.GetDefaultView(entities);
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription("Name", direction));
foreach (object entity in entities) {
if (entity is ICascadingSetup cascadingSetup) {
ConfigureSortingRecursive(cascadingSetup.Children, direction);
}
}
}
每当你有类似对象的这种树状表示时,总是值得检查递归是否是简化事情的一种选择。