예제 #1
0
        // Note about special case: members with CascadeDelete attribute.
        // Demo case setup. 3 entities, IBook, IAuthor, and IBookAuthor as link table; IBookAuthor references IBook with CascadeDelete,
        // and references IAuthor without cascade.
        // Because of CascadeDelete, when we delete IBook and IBookAuthor in one operation, the order of IBook vs IBookAuthor does not matter:
        // even if IBook comes before IBookAuthor, delete will succeed because of cascade delete of IBookAuthor.
        // The problem case is when we are deleting IBook and IAuthor, without explicitly deleting IBookAuthor.
        // In this case IAuthor should be deleted after IBook - otherwise still existing IBookAuthor record
        // would prevent it from deleting. As there's no explicit IBookAuthor in delete set, and there's
        // no FK links between IAuthor and IBook - then they may come to delete in any order, and trans might fail.
        // The solution is to introduce an extra direct link between IBook and IAuthor in abstract SCC node tree.
        // This extra link will ensure proper topological ordering of IBook and IAuthor.
        // Note that we still need to add link between IBookAuthor and IBook - for proper ordering of inserts.
        private void ComputeTopologicalIndexes()
        {
            // Run SCC algorithm
            var g = new SccGraph();

            //Perform SCC analysis.
            foreach (var ent in Model.Entities)
            {
                ent.SccVertex = g.Add(ent);
            }
            //setup links
            foreach (var ent in Model.Entities)
            {
                var cascadeMembers    = new List <EntityMemberInfo>();
                var nonCascadeMembers = new List <EntityMemberInfo>();
                foreach (var member in ent.RefMembers)
                {
                    var targetEnt = member.ReferenceInfo.ToKey.Entity;
                    ent.SccVertex.AddLink(targetEnt.SccVertex);
                    if (member.Flags.IsSet(EntityMemberFlags.CascadeDelete))
                    {
                        cascadeMembers.Add(member);
                    }
                    else
                    {
                        nonCascadeMembers.Add(member);
                    }
                }//foreach member
                //For all cascade member (IBookAuthor.Author) targets add direct links to all non-cascade member targets
                // (from IBook to IAuthor)
                foreach (var cascMember in cascadeMembers)
                {
                    var cascTarget = cascMember.ReferenceInfo.ToKey.Entity;
                    foreach (var nonCascMember in nonCascadeMembers)
                    {
                        var nonCascTarget = nonCascMember.ReferenceInfo.ToKey.Entity;
                        cascTarget.SccVertex.AddLink(nonCascTarget.SccVertex);
                    }
                } //foreach cascMember
            }     //foreach ent

            //Build SCC
            var sccCount = g.BuildScc();

            //read scc index and clear vertex fields
            foreach (var ent in Model.Entities)
            {
                var v = ent.SccVertex;
                ent.TopologicalIndex = v.SccIndex;
                if (v.NonTrivialGroup)
                {
                    ent.Flags |= EntityFlags.TopologicalGroupNonTrivial;
                }
                ent.SccVertex = null;
            }
        }
예제 #2
0
파일: HelpersTests.cs 프로젝트: radtek/vita
        // Builds a sample graph from http://en.wikipedia.org/wiki/Strongly_connected_components
        private static void SetupSampleGraph(SccGraph gr)
        {
            var a = gr.Add("a");
            var b = gr.Add("b");
            var c = gr.Add("c");
            var d = gr.Add("d");
            var e = gr.Add("e");
            var f = gr.Add("f");
            var g = gr.Add("g");
            var h = gr.Add("h");

            //links
            a.AddLink(b);
            b.AddLink(e, f, c);
            c.AddLink(d, g);
            d.AddLink(c, h);
            e.AddLink(a, f);
            f.AddLink(g);
            g.AddLink(f);
            h.AddLink(g, d);
        }