实体框架自引用多对多与有效负载(物料清单 BOM)

发布于 2024-09-27 15:33:33 字数 3683 浏览 12 评论 0原文

我不久前问过这个问题,但没有答案,我相信这可能是 EF 最奇怪的实现,尽管它非常实用。这是我之前的帖子:

实体框架自引用分层多对多

我决定再次询问附加关键字 Payload 并获得更清晰的理解。

在 Apress 出版物中:Entity Framework 4.0 Recipes: A Problem-Solution Approach,第 2-6 页的配方 2-6。 26 的标题为使用有效负载建模多对多关系。秘诀 2-7 的标题是“建立自参照关系模型”。

阅读这些内容将为您了解我的问题奠定基础,不同之处在于我有一个带有效负载的自引用多对多,据我所知,这本书或宇宙中的任何地方都没有讨论过。

简而言之,我有一个包含 ID 和类型字段的资源表。我还有一个 ResourceHierarchy 表,它用作联结表或桥接表,因为它有一个由 Parent_ID 和 Child_ID 组成的复合主键以及一个复合外键。因此,资源实体可以充当子资源或父资源,或两者兼而有之。

到目前为止,实体框架已生成资源实体,但 ResourceHierarchy 实体实际上对 EDMX 设计器是隐藏的,因为在 EDMX 文件中,它仅被视为关系而不是实体。

生成的资源实体将具有诸如 Resources 和 Resources1 之类的导航属性,我将其重命名为“Parents”和“Children”。

所以我可以编写这样的代码:(它不执行任何操作,我只是显示一些示例)

List<Resource> listResources = Context.Resouces.ToList()
foreach (Resource resc in listResources)
{
List<Resource> listParents = resc.Parents.ToList()
List<Resource> listChildren = resc.Children.ToList()
foreach (Resource parent in listParents)
{
Console.WriteLine(parent.Type);
}
foreach (Resource child in listChildren)
{
Console.WriteLine(child.Type);
}
resc.Children.Add(new Resource());
Console.WriteLine(resc.Parents.First().Children.First().Type);
}

假设我有一个由其他两个资源共享的资源。另外两个资源将是该资源的父资源。所述资源也是其每个父母的唯一孩子。是的,一个资源可以有三个或更多“父母”,如果您愿意的话甚至可以有两个父亲,但是祖先会共享一个孩子吗?不在我的监视之下。所以无论如何......我们必须从现实世界的场景来思考这一点,这样它才能从这一点开始变得有意义。

下面是一些让我们开始的代码:

Resource parent1 = new Resource();
Resource parent2 = new Resource();
Resource child = new Resource();

parent1.Type = "WidgetA";
parent2.Type = "WidgetB";
child.Type = "1/4 Screw"

parent1.Children.Add(child);
parent2.Children.Add(child);

Product product1 = new Product();
Product product2 = new Product();

product1.Resources.Add(parent1);
product2.Resources.Add(parent2);

所以我们有两个带有螺丝的小部件。 WidgetA 和 WidgetB 在网站上列为产品。如果WidgetA卖了,WidgetB的螺丝会怎样?现在您看到我们需要资源实体上的数量属性。

快进几个月,我现在正在我的项目中,在意识到 EF 的局限性后,我采取了胎儿的姿势。

这部分变得有点复杂。如果

child.Quantity = 4
parent1.Quantity = 1
parent2.Quantity = 1

我们如何知道或设置它,以便我们可以将 2 个子项分配给 Parent1,将 2 个子项分配给 Parent2?

这只能通过添加另一个数量(int)列来完成,我们将其称为“必需”到 ResourceHierarchy 表,因此它看起来像:

Parent_ID int not null,
Child_ID int not null,
Required int not null default 1

因此,我们已将有效负载附加到数据库中的 ResourceHierarchy 实体。如果我们从 EDMX 设计器重新生成模型,ResourceHierarchy 就不再是关系,而是现在的实体。如果我选择仅从 EDMX 设计器刷新 ResourceHierarchy 表,我可以在存储模型中看到“Required”属性,但它不在概念或映射模型中,因为 ResourceHierarchy 将是一种关系。但是,如果我删除资源表和 ResourceHierarchy 表并重新生成它们,则 ResourceHierarchy 表现在可以通过“必需”列可见,并且它现在是一个实体。

可以使用此设置,但它比简单地访问 ResourceHierarchy 关系并检索必需属性要困难得多。即使ResourceHierarchy EntityType 在存储模型中包含Required 属性,在访问AssociationSet 后我也无法从代码中访问Required 属性。如果 ResourceHierarchy 表是 EF 中的关系,则它在存储模型中看起来像这样。

<EntityType Name="ResourceHierarchy">
          <Key>
            <PropertyRef Name="Parent_ID" />
            <PropertyRef Name="Child_ID" />
          </Key>
          <Property Name="Parent_ID" Type="int" Nullable="false" />
          <Property Name="Child_ID" Type="int" Nullable="false" />
          <Property Name="Required" Type="int" Nullable="false" />
</EntityType>

如果我尝试合并生成的 EDMX 文件,则会收到错误消息,告诉我 ResourceHierarchy 可以是实体或关系,但不能同时是两者。

这称为带有效负载的多对多。尝试使用自引用层次结构来实现这一点在 EF 中是一场噩梦。我正在使用 VS2010、SQL 2008 和 .NET 4.0 Framework。

这个概念是,我想要拥有由资源组成的产品,这些资源本身又由其他资源组成或用于组成其他资源,并且每个产品都需要一定数量的资源。它基本上是物料清单 BOM。 EF不支持BOM模型吗?

SQL Server 2008 中的新 HIERARCHYID 功能是否会有所帮助?

I asked this question a while back without an answer, I believe it may be the most bizarre implementation for the EF, although it is quite practical. Here is my previous post:

Entity Framework Self Referencing Hierarchical Many To Many

I've decided to ask again with the additional keyword Payload and a clearer understanding.

In the Apress publication: Entity Framework 4.0 Recipes: A Problem-Solution Approach, recipe 2-6 on pg. 26 is titled Modeling a Many-To-Many Relationship with a Payload. Recipe 2-7 is titled Modeling a Self-Referential Relationship.

Reading that would give you a foundation for what my problem is, the difference is that I have a Self-Referential Many-To-Many with Payload which is not discussed in the book or anywhere in the universe to my knowledge.

To put it very simply I have a Resource table with ID and Type fields. I also have a ResourceHierarchy table which serves as the junction or bridge table in that it has a composite primary key made up of a Parent_ID and Child_ID and a composite foreign key. So a Resource entity can either serve as a Child Resource or Parent Resource or BOTH.

By now the Entity Framework would have generated the Resource Entity but the ResourceHierarchy Entity would actually be hidden from the EDMX Designer since in the EDMX file it is being treated as only a relationship and not an entity.

The generated Resource Entity will have navigation properties like Resources and Resources1 which I renamed Parents and Children.

So I can write code like this: (It doesn't do anything I'm just showing some examples)

List<Resource> listResources = Context.Resouces.ToList()
foreach (Resource resc in listResources)
{
List<Resource> listParents = resc.Parents.ToList()
List<Resource> listChildren = resc.Children.ToList()
foreach (Resource parent in listParents)
{
Console.WriteLine(parent.Type);
}
foreach (Resource child in listChildren)
{
Console.WriteLine(child.Type);
}
resc.Children.Add(new Resource());
Console.WriteLine(resc.Parents.First().Children.First().Type);
}

Lets say I have a Resource that is being shared by two other Resouces. The two other resources would be the Parents of said Resource. Said Resource is also the only Child of each of it's Parents. Yes, a Resource can have three or more "Parents", even two dads if you like but would ancestors share a child? Not on my watch. So anyway... we have to think of this from a real world scenario for it to make sense from this point on.

Here is some code to get us started:

Resource parent1 = new Resource();
Resource parent2 = new Resource();
Resource child = new Resource();

parent1.Type = "WidgetA";
parent2.Type = "WidgetB";
child.Type = "1/4 Screw"

parent1.Children.Add(child);
parent2.Children.Add(child);

Product product1 = new Product();
Product product2 = new Product();

product1.Resources.Add(parent1);
product2.Resources.Add(parent2);

So we have two widgets that have a screw.
WidgetA and WidgetB are listed as products on a website. What if WidgetA sells, what will happen to WidgetB's screw? So now you see we need a Quantity property on the Resource Entity.

Fast forward many months to were I currently am in my project and assume the fetal position after realizing how limited the EF is.

This part gets a little more complicated. If

child.Quantity = 4
parent1.Quantity = 1
parent2.Quantity = 1

How will we know or set it up so that we can assign 2 of the child to parent1 and 2 of the child to parent2?

That can only be done via adding another quantity(int) column which we'll call "Required" to the ResourceHierarchy table so it would look like:

Parent_ID int not null,
Child_ID int not null,
Required int not null default 1

So we've attached the payload to the ResourceHierarchy Entity in the db. If we regenerate the model from the EDMX designer ResourceHierarchy is no longer a Relationship but is now an Entity. If I choose instead to only Refresh the ResourceHierarchy table from the EDMX designer I can see the Required property in the Storage Model but it is no where in the Conceptual or Mapping models since the ResourceHierarchy would be a relationship. However if I delete the Resource table and the ResourceHierarchy table and regenerate them the ResourceHierarchy table is now visible with the Required column and it is now an Entity.

It is possible to work with this setup but it's so much more difficult than simply being able to access the ResourceHierarchy Relationship and retrieve the Required property. Even if the ResourceHierarchy EntityType includes the Required property in the Storage Model I cannot access the Required property from code after accessing the AssociationSet. If the ResourceHierarchy table is a relationship in the EF it looks like this in the Storage Model.

<EntityType Name="ResourceHierarchy">
          <Key>
            <PropertyRef Name="Parent_ID" />
            <PropertyRef Name="Child_ID" />
          </Key>
          <Property Name="Parent_ID" Type="int" Nullable="false" />
          <Property Name="Child_ID" Type="int" Nullable="false" />
          <Property Name="Required" Type="int" Nullable="false" />
</EntityType>

If I try to merge the generated EDMX files I get the error telling me that the ResourceHierarchy can either be an Entity or a Relationship but not both.

This is called a Many-To-Many with Payload. Trying to implement this with a Self-Referential Hierarchy is a nightmare in the EF. I'm working with VS2010, SQL 2008, and the .NET 4.0 Framework.

The concept is that I want to have Products that are made up of Resources which themselves are made up of other Resources or serve to make up other Resources and each one requires a certain quantity amount of Resources. It's basically a Bill of Materials BOM. Does the EF not support the BOM model?

Would the new HIERARCHYID feature in SQL Server 2008 help by any chance?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

私野 2024-10-04 15:33:33

所以我最终得到了一个令人惊讶的优雅解决方案。

CREATE TABLE Resource
(
ID INT NOT NULL,
Type VARCHAR(25) NOT NULL
)

ALTER TABLE Resource
ADD CONSTRAINT PK_Resource PRIMARY KEY (ID)

CREATE TABLE ResourceHierarchy
(
Ancestor_ID INT NOT NULL,
Descendant_ID INT NOT NULL,
Required INT NOT NULL DEFAULT 1
)

ALTER TABLE ResourceHierarchy
ADD CONSTRAINT PK_ResourceHierarchy PRIMARY KEY (Ancestor_ID, Descendant_ID)
ALTER TABLE ResourceHierarchy
ADD CONSTRAINT FK_Ancestors FOREIGN KEY (Ancestor_ID) REFERENCES Resource (ID)
ALTER TABLE ResourceHierarchy
ADD CONSTRAINT FK_Descendants FOREIGN KEY (Descendant_ID) REFERENCES Resource (ID)

生成 EDMX 后,我将资源实体导航属性从 ResourceHierarchy 重命名为 DescendantRelationships,将 ResourceHierarchy1 重命名为 AncestorRelationships。然后,我将 ResourceHierarchy 实体导航属性从 Resource 重命名为 Descendant,将 Resource1 重命名为 Ancestor。

而之前我可以编写这样的代码:

Resource resource = new Resource();
resource.Descendants.Add(new Resource());
foreach (Resource descendant in resource.descendants)
{
descendant.Type = "Brawr";
List<Resource> ancestors = descendant.Ancestors.ToList();
}

当然,这种方法不允许我访问 required 属性。

现在我必须执行以下操作:

Resource ancestor = new Resource();
Resource descendant = new Resource();

ResourceHierarchy rh = new ResourceHierarchy { Ancestor = ancestor, Descendant = descendant, Required = 1 };

ancestor.DescendantRelationships.Add(rh);

但是检查一下,我现在可以像这样访问“Required”属性:

int req = ancestor.DescendantRelationships.First().Required;

可以将“Required”字段重命名为“RequiredDescendants”,因为“后代”不需要所需数量的“祖先”,只有“祖先”需要指定有多少“后代”是必需的。

所以这是一种跳跃,但却是一种优雅的跳跃。

请让我知道您的想法,特别是如果我忽略了一个问题或其他问题。

So I ended up with a surprisingly graceful solution.

CREATE TABLE Resource
(
ID INT NOT NULL,
Type VARCHAR(25) NOT NULL
)

ALTER TABLE Resource
ADD CONSTRAINT PK_Resource PRIMARY KEY (ID)

CREATE TABLE ResourceHierarchy
(
Ancestor_ID INT NOT NULL,
Descendant_ID INT NOT NULL,
Required INT NOT NULL DEFAULT 1
)

ALTER TABLE ResourceHierarchy
ADD CONSTRAINT PK_ResourceHierarchy PRIMARY KEY (Ancestor_ID, Descendant_ID)
ALTER TABLE ResourceHierarchy
ADD CONSTRAINT FK_Ancestors FOREIGN KEY (Ancestor_ID) REFERENCES Resource (ID)
ALTER TABLE ResourceHierarchy
ADD CONSTRAINT FK_Descendants FOREIGN KEY (Descendant_ID) REFERENCES Resource (ID)

When the EDMX was generated I renamed the Resource Entity navigation properties from ResourceHierarchy to DescendantRelationships and ResourceHierarchy1 to AncestorRelationships. I then renamed the ResourceHierarchy Entity navigation properties from Resource to Descendant and Resource1 to Ancestor.

Whereas before I could write code like this:

Resource resource = new Resource();
resource.Descendants.Add(new Resource());
foreach (Resource descendant in resource.descendants)
{
descendant.Type = "Brawr";
List<Resource> ancestors = descendant.Ancestors.ToList();
}

Of course this approach did not allow me to access the Required property.

Now I must do the following:

Resource ancestor = new Resource();
Resource descendant = new Resource();

ResourceHierarchy rh = new ResourceHierarchy { Ancestor = ancestor, Descendant = descendant, Required = 1 };

ancestor.DescendantRelationships.Add(rh);

But check it out I can now get to the Required property like so:

int req = ancestor.DescendantRelationships.First().Required;

One might rename the Required field to RequiredDescendants since Descendants don't need a required amount of Ancestors, only Ancestors need to specify how many Descendants are required.

So it's a hop, but a graceful one.

Please let me know your thoughts, especially if I've overlooked a gotcha or something.

怪我太投入 2024-10-04 15:33:33

需要注意的事情...

当我们想要向资源添加后代时,我们需要记住 DescendantRelationships 为我们提供了层次结构,其中引用的资源充当其他资源的后代。

因此,为了向资源添加后代,我们必须执行以下操作:

Resource resource = new Resource { Type = "WidgetA" };
Resource descendant = new Resource { Type = "Screw" };
resource.AncestorRelationships.Add(new ResourceHierarchy { Descendant = descendant, Required = 1 };

当然,这一切都取决于您如何命名导航属性,我只是说要小心。 AncestorRelationships 将是转到导航属性,以便添加后代,反之亦然。更好的做法可能是将 AncestorRelationships 重命名为 AncestorRoles,将 DescendantRelationships 重命名为 DescendantRoles。

AncestorRoles 将转换为 ResourceHierarchiesWhereCurrentResourceIsAnAncestor。
DescendantRoles 将转换为 ResourceHierarchiesWhereCurrentResourceIsADescendant。

所以我们可以这样做:

// print descendant types
foreach (ResourceHierarchy rh in resource.AncestorRoles)
{
Console.WriteLine(rh.Descendant.ResourceType.Type);
}

很抱歉对术语进行了如此大的改变,但我认为这有助于理解正在发生的事情。

Something to watch out for...

When we want to add a descendant to a resource we need to remember that DescendantRelationships gives us the hierarchy where the referenced resource is acting as descendants to other resources.

So in order to add a descendant to a resource we must do the following:

Resource resource = new Resource { Type = "WidgetA" };
Resource descendant = new Resource { Type = "Screw" };
resource.AncestorRelationships.Add(new ResourceHierarchy { Descendant = descendant, Required = 1 };

Of course this all depends on how you name your navigation properties, I'm just saying be careful. AncestorRelationships would be the go to navigation property in order to add descendants and vice versa. A better thing to do might be to rename AncestorRelationships to AncestorRoles and DescendantRelationships to DescendantRoles.

AncestorRoles would translate to ResourceHierarchiesWhereCurrentResourceIsAnAncestor.
DescendantRoles would translate to ResourceHierarchiesWhereCurrentResourceIsADescendant.

So we could do:

// print descendant types
foreach (ResourceHierarchy rh in resource.AncestorRoles)
{
Console.WriteLine(rh.Descendant.ResourceType.Type);
}

Sorry to change up the nomenclature so much but I think it helps understand what's going on.

心如荒岛 2024-10-04 15:33:33

MSDN 库链接: http://msdn.microsoft.com/en-us/ Library/ms742451.aspx 的标题为“PropertyPath XAML 语法”,并有一个标题为“源遍历(绑定到集合的层次结构)”的部分。

这是我要使用的 HierarchicalDataTemplate:

<HierarchicalDataTemplate DataType="{x:Type Inventory:Resource}" ItemsSource="{Binding Path=AncestorRoles/Descendant}">
<CustomControls:ResourceTreeItem Type="{Binding ResourceType.Type}"/>
</HierarchicalDataTemplate>

仅显示第一个资源。以下代码运行后,TreeView 将在 TreeView 中显示一个 ResourceTreeItem。

ObservableCollection<Resource> Resources = new ObservableCollection<Resource>
Resources.Add(new Resource { ResourceType.Type = "WidgetA" });
MyTreeView.ItemsSource = Resources;

这样就可以了。但是,当我运行以下代码时,TreeView 不会更新。

Resource resource = MyTreeView.Items[0] as Resource;
resource.AncestorRoles.Add( new ResourceHierarchy { Descendant = new Resource { ResourceType = "Screw" }, Required = 1 } )

即使我获取 TreeView.ItemsSource 的 CollectionViewSource 并调用 Refresh() 它也不会显示。我检查了三次关系,一切都在那里。

我认为这是 PropertyPath Traversal 语法的错误。

解决方案是将 TreeParent 属性添加到 Resource 分部类声明中,并利用 3 个 ValueConverters,这是一个很长的故事,但这是因为数据上下文自然地从 Resource 交替到 ResourceHierarchy。 requiredConverter 是检查 TreeParent 并查找必需属性有效负载的转换器。

class ValidatorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Resource resource = value as Resource;
            ResourceHierarchy rh = value as ResourceHierarchy;
            if (resource != null)
            {
                value = resource;
            }
            else if (rh != null)
            {
                value = rh.Descendant;
            }

            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    class ResourceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Resource resource = value as Resource;
            ResourceHierarchy hierarchy = value as ResourceHierarchy;

            if (resource != null)
            {
                if (resource.AncestorRoles.Count > 0)
                {
                    value = resource.AncestorRoles;
                }
                else
                {
                    value = resource;
                }
            }
            else if (hierarchy != null)
            {
                value = hierarchy.Descendant.AncestorRoles;
            }

            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    class RequiredConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Resource resource = (Resource)value;
            Resource parent = ((Resource)value).TreeParent as Resource;
            if (parent != null)
            {
                value = parent.AncestorRoles.Where(p => p.Descendant == resource).First().Required;
            }
            else
            {
                value = 0;
            }

            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

这是最终的 HierarchicalDataTemplate:

<HierarchicalDataTemplate DataType="{x:Type Inventory:Resource}" ItemsSource="{Binding Path=., Converter={StaticResource resourceconv}}">
<StackPanel DataContext="{Binding Path=., Converter={StaticResource validatorconv}}">
<CustomControls:ResourceTreeItem Required="{Binding Path=., Converter={StaticResource requiredconv}}" Free="{Binding Free}" OnHand="{Binding OnHand, Mode=TwoWay}" Type="{Binding ResourceType.Type}"/>
</StackPanel>
</HierarchicalDataTemplate>

StackPanel 仅用于添加另一个 DataContext 层。我保留了 Free、OnHand 和 Type 属性,这样您就可以看到 3 个属性正在从 StackPanels DataContext 接收绑定,而Required 属性正在像疯子一样做这件事。

因此,如果您需要有效负载,那么 EF 可能不适合您。

The MSDN Libary link : http://msdn.microsoft.com/en-us/library/ms742451.aspx is titled PropertyPath XAML Syntax and has a section titled Source Traversal (Binding to Hierarchies of Collections)

This is the HierarchicalDataTemplate I want to use:

<HierarchicalDataTemplate DataType="{x:Type Inventory:Resource}" ItemsSource="{Binding Path=AncestorRoles/Descendant}">
<CustomControls:ResourceTreeItem Type="{Binding ResourceType.Type}"/>
</HierarchicalDataTemplate>

Only the first Resource is displayed. After the following code runs the TreeView shows one ResourceTreeItem in the TreeView.

ObservableCollection<Resource> Resources = new ObservableCollection<Resource>
Resources.Add(new Resource { ResourceType.Type = "WidgetA" });
MyTreeView.ItemsSource = Resources;

So that works. However when I run the following code the TreeView is not updated.

Resource resource = MyTreeView.Items[0] as Resource;
resource.AncestorRoles.Add( new ResourceHierarchy { Descendant = new Resource { ResourceType = "Screw" }, Required = 1 } )

Even if I get the CollectionViewSource of the TreeView.ItemsSource and call Refresh() it doesn't show up. I triple checked the relationships and it's all there.

I think it's a bug with the PropertyPath Traversal syntax.

The solution was to add a TreeParent property to the Resource partial class declaration and utilize 3 ValueConverters which is a long story but it's because the datacontext naturally alternates from a Resource to a ResourceHierarchy. The RequiredConverter is the one that checks the TreeParent and finds the Required property Payload.

class ValidatorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Resource resource = value as Resource;
            ResourceHierarchy rh = value as ResourceHierarchy;
            if (resource != null)
            {
                value = resource;
            }
            else if (rh != null)
            {
                value = rh.Descendant;
            }

            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    class ResourceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Resource resource = value as Resource;
            ResourceHierarchy hierarchy = value as ResourceHierarchy;

            if (resource != null)
            {
                if (resource.AncestorRoles.Count > 0)
                {
                    value = resource.AncestorRoles;
                }
                else
                {
                    value = resource;
                }
            }
            else if (hierarchy != null)
            {
                value = hierarchy.Descendant.AncestorRoles;
            }

            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    class RequiredConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Resource resource = (Resource)value;
            Resource parent = ((Resource)value).TreeParent as Resource;
            if (parent != null)
            {
                value = parent.AncestorRoles.Where(p => p.Descendant == resource).First().Required;
            }
            else
            {
                value = 0;
            }

            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

And here is the final HierarchicalDataTemplate:

<HierarchicalDataTemplate DataType="{x:Type Inventory:Resource}" ItemsSource="{Binding Path=., Converter={StaticResource resourceconv}}">
<StackPanel DataContext="{Binding Path=., Converter={StaticResource validatorconv}}">
<CustomControls:ResourceTreeItem Required="{Binding Path=., Converter={StaticResource requiredconv}}" Free="{Binding Free}" OnHand="{Binding OnHand, Mode=TwoWay}" Type="{Binding ResourceType.Type}"/>
</StackPanel>
</HierarchicalDataTemplate>

The StackPanel only serves to add another DataContext layer. I left in the Free, OnHand and Type properties so you could see that 3 properties are receiving their binding from the StackPanels DataContext and the Required property is doing it's thing like a mad man.

So the moral is if you need a Payload maybe the EF isn't for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文