AM and Programming Models

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

AM and Programming Models

Chris
Hello,

Our programming group is beginning to use .NET and Entity Framework to develop new applications. Can Entity Framework work directly with Anchor Modeling structures? Can it properly consume the objects and relationships? Should it be directed to use just the 3NF views?

Does anyone else have experience with integrating AM with programming models?

Thanks!
Chris
Reply | Threaded
Open this post in threaded view
|

Re: AM and Programming Models

roenbaeck
Administrator
I am not familiar with Entity Framework, so I can't answer that specific question. If you want something Object-Relational-mapping-like, then you may want to work directly with the 6NF tables, translating object properties to attributes for example. This is quite a large undertaking though, but could be made reusable.

If you want to use AM more like a traditional database from your program, then the 3NF views and functions should provide all that is necessary. There are triggers on the latest view, making it behave much like a regular table with respect to insert, update, and delete statements.

I have used AM as a traditional database and can say that it works well and I am aware of two companies who use AM more ORM-like. One of them made an object persistance API similar to Hibernate and the other had an in-memory AM representation (anchors, ties, knots, attributes as objects).
Reply | Threaded
Open this post in threaded view
|

Re: AM and Programming Models

Chris
Thank you for the response. That answers my question. There might be some  manual effort involved, but it sounds like it should work fine with the 3NF views as long as they follow AM principles.

Thanks,
Chris
Reply | Threaded
Open this post in threaded view
|

Re: AM and Programming Models

SteveCooperOrg
In a previous workplace, we managed to get at least a simple integration between EF and AM, based on about a day's fiddling about. It was limited, and someone else did it, but I'll try to outline the approach I think he took.

  1) Use Model-First Entity Framework to duplicate the design of your AM entities. Eg, if you have an AM anchor with six attributes, then create an EF entity with the same six attributes.
  2) In the EF model, set the entity to read from the 3NF view.

You can then write LINQ statements like;

    from obj in MyAnchor
    where obj.Title = 'foo'

and it'll translate to the appropriate T-SQL query using Entity Framework. That's read-only covered. To allow edits;

  3) Create stored procedures for insert, update, and delete for each entity, eg sp_insert_Customer, sp_update_Customer, sp_delete_Customer.
  4) In the EF model, set the entity to insert/update/delete using the stored procedures.

You can now insert/update/delete items in your EF context, and context.SaveChanges() will fire the appropriate stored procedures for modified entities.

There is obviously some duplication at play here -- the schema needs to be duplicated between the online Anchor Modelling tool and in the Entity Framework model in the EDMX file, but I think there's the possibility of automating this process using XSLT or similar. Generating the insert/update/delete stored procedures could also be automated.

Big questions for me are;

1) How would relationships work? I've seen this work for attribute values, but I don't know whether something could be done to unify AM's concept of *ties* with EF's concept of *navigation properties*.

2) Can EF's support for inheritance be modeled using AM? Currently, EF allows you to build systems where concrete entities inherit from abstract entities, and builds and manages the appropriate tables and foreign key constraints underneath. I don't know if AM deals with any form of inheritance, so you may need to flatten all your EF entities out somehow, possibly by using Table-Per-Concrete-Type? (http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx)

All of this was based on an older version of the AM tools, and it's been a while, so apologies for any inaccuracy -- I hope it's enough for people to start kicking around the ideas, at least.
Reply | Threaded
Open this post in threaded view
|

Re: AM and Programming Models

Chris
Thank you very much for this great information. This will definately help point us in the right direction. I'll post back to this thread if/when programming or I have a chance to work with it. Hopefully this will be useful to others as well and we can expand the topic even further as time goes on.

Thanks again!
Chris
Reply | Threaded
Open this post in threaded view
|

Re: AM and Programming Models

SteveCooperOrg
I've now had some minor success with Entity Framework code-first. Here's the approach;

You'll need an EDMX file that describes your EF schema. Luckily, you can write this out using `System.Data.Entity.Infrastructure.EdmxWriter`. I use code like this to give you the contents of the EDMX file implied by a code-first DbContext;

        public string ToEdmx(System.Data.Entity.DbContext context)
        {
            var sb = new StringBuilder();

            using (var textWriter = new StringWriter(sb))
            using (var xmlWriter = System.Xml.XmlWriter.Create(textWriter, new System.Xml.XmlWriterSettings { Indent = true, IndentChars = "    " }))
            {
                System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(context, xmlWriter);
                textWriter.Flush();
            }
           
            return sb.ToString();
        }

Now you need to search through the EDMX file for Entity and Attribute elements. Use the ones under the 'StorageModels' element as this contains the SQL Server data types for the columns, and you'll need that.

Go through the Entities and Attributes, and assign each one a Mnemonic -- the 2- or 3-character code required by Anchor Modeling. I save this info off in an XML file format I've created that looks like this -- it's intended to bridge between EF and AM;

    <Schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <Entities>
            <Entity Descriptor="Item" Mnemonic="IT">
                <Attributes>
                    <Attribute Descriptor="Id" Mnemonic="IDD" IsId="true" SqlType="int" />
                    <Attribute Descriptor="Code" Mnemonic="COD" IsId="false" SqlType="nvarchar(max)" />
                    <Attribute Descriptor="IsMandatory" Mnemonic="ISM" IsId="false" SqlType="bit" />
                    ...
                   

This intermediate schema is used twice; first, to create an Anchor Modeling XML file, like that produced by the Online Modeler tool. This will look something like

    <schema>
      <metadata format="0.97" temporalization="bi" date="2014-01-10" time="10:06:53" />
        <anchor mnemonic="IT" descriptor="Item" identity="int">
        <metadata capsule="dbo" generator="true" />
        <attribute mnemonic="COD" descriptor="Code" dataRange="nvarchar(max)">
          <metadata capsule="dbo" />
        </attribute>
        <attribute mnemonic="ISM" descriptor="IsMandatory" dataRange="bit">
          <metadata capsule="dbo" />
        </attribute>
        ...

Now you can load this into the online modeler and use it to generate the SQL which will create your database. So now, you have an anchor model DB in the shape of your Entity Framework Code-First DbContext!

Second, Anchor Modeling imposing a naming scheme on your database, so you need to tell Entity Framework where to look for things. Eg, instead of looking in the [Item] table, use the [lIT_Item] view. Instead of looking for the [ItemName] column, look for [IT_ITN_Item_ItemName].

You do this inside your subclass of DbContext. In OnModelCreating(), you need to use the intermediate schema description as described above and alias all the entities and properties to use new view names and column names; eg, to alias an entity to look in the Anchor Modeling l-view, use this;

            foreach (Entity entity in metaModel.Entities)
            {
                // entities should load from l-views
                modelBuilder.Types()
                    .Where(t => t.Name == entity.Descriptor)
                    .Configure(t => t.ToTable(entity.ViewName));
            }

You'll also need to alias the attributes using something like

                    // properties should read from long-form column names
                    modelBuilder.Properties()
                        .Where(p => p.DeclaringType.Name == entity.Descriptor && p.Name == attribute.Descriptor)
                        .Configure(p => p.HasColumnName(attribute.ViewName));


You'll also need to turn off EF's built-in attempts to build tables when the database is initialized. Use something like this before the context is used;

    System.Data.Entity.Database.SetInitializer<MyContext>(new NullDatabaseInitializer<MyContext>());

And remove any Configuration.cs file and associated migrations.

At this point, you can load your context. It'll connect to the DB, avoid creating the EF tables, know the correct aliases for the views and columns to use, and allow reads from the database using EF code-first and LINQ.

I've not done anything with relationships of any kind yet.

I know there's a lot there, but I hope it's useful to people down the line.

    Steve