Print Page | Close Window

DomainModelTemplate

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=3578
Printed Date: 13-May-2026 at 2:59am


Topic: DomainModelTemplate
Posted By: Vonzkie
Subject: DomainModelTemplate
Date Posted: 15-Aug-2012 at 12:42am
Hi,

I have read about DomainModelTemplate to customize code generation, however, i don't have resource materials to review. 
Here's what I want to accomplished, all of our Entities have intConcurrencyID field, we want to automate the process using DomainModelTemplate to make the field ConcurrencyStrategy to AutoIncrement and the ConcurrencyMode to Fixed.

This is my first attempt to do it:

public class MyTemplate : DomainModelTemplate {

    public MyTemplate(Microsoft.VisualStudio.TextTemplating.TextTransformation textTransformation)
           : base(textTransformation) {}

    protected override void WriteEntityDataPropertyAttributes(EdmPropertyWrapper property) {
if (property.Name == "intConcurrencyID") {
WriteAttribute("IbEm.ConcurrencyStrategy(IbEm.ConcurrencyStrategy.AutoIncrement)");
}

        base.WriteEntityDataPropertyAttributes(property);
    }
}

I successfully add attribute to my field but the problem is the PropertyMetadata,

public static readonly IbEm.DataEntityProperty<tblSMSecurityListing, int> intConcurrencyID = new IbEm.DataEntityProperty<tblSMSecurityListing, int>("intConcurrencyID", false, false, IbEm.ConcurrencyStrategy.None, false, null);

The ConcurrencyStrategy is still set to none and i don't know how to edit this using the DomainModelTemplate.

Can you help me on this and if you could provide me some tutorials on how to customize a Devforce model using that technique?

Thanks,
Von





Replies:
Posted By: Vonzkie
Date Posted: 15-Aug-2012 at 3:18am
I tried adding to my code and I ended up doing this:

public MyTemplate(Microsoft.VisualStudio.TextTemplating.TextTransformation textTransformation)
           : base(textTransformation) {}

    protected override void WriteEntityDataPropertyAttributes(EdmPropertyWrapper property) {
if (property.Name == "intConcurrencyID") {
WriteAttribute("IbEm.ConcurrencyStrategy(IbEm.ConcurrencyStrategy.AutoIncrement)");
}

        base.WriteEntityDataPropertyAttributes(property);
    }

       protected override void WriteDataEntityPropertyDefinition(EdmPropertyWrapper property)
       {
           if (property.Name == "intConcurrencyID")
           {
               WriteLine(String.Format("/// <summary>The {0} <see cref=\"T:IbEm.DataEntityProperty\"/>. </summary>", property.Name));

               var type = property.IsNullable ? "System.Nullable<int>" : "int";

               WriteLine(String.Format("public static readonly IbEm.DataEntityProperty<{0}, {1}> intConcurrencyID = new IbEm.DataEntityProperty<{0}, {1}>(\"intConcurrencyID\", {2}, false, IbEm.ConcurrencyStrategy.AutoIncrement, false, null);", property.ParentType.Name, type, property.IsNullable.ToString().ToLower()));
           }
           else
           {
               base.WriteDataEntityPropertyDefinition(property);
           }
       }
}


I was able to replace this part:
public static readonly IbEm.DataEntityProperty<tblSMSecurityListing, int> intConcurrencyID = new IbEm.DataEntityProperty<tblSMSecurityListing, int>("intConcurrencyID", false, false, IbEm.ConcurrencyStrategy.None, false, null);

However, concurrency is not yet working and I really need to configure it manually in the EDM designer by setting the columns' ConcurrencyStrategy and ConcurrencyMode for it to work properly.

I thought that EntityManager just look on the designer.cs stuffs to perform concurrency checking but it seems that edmx csdl should be sync with the code behinf or I just missed something here?

Thanks,
Von



Posted By: mgood
Date Posted: 15-Aug-2012 at 9:28am
Von,
Concurrency detection is performed by EntityFramework not DevForce as described below. DevForce adds the ability to maintain the concurrency column for you, that's what the ConcurrencyStrategy does. But concurrency detection is performed by EF and it only does it if the EDM has the "Concurrency Mode" set to "Fixed".

http://drc.ideablade.com/xwiki/bin/view/Documentation/save-concurrency - http://drc.ideablade.com/xwiki/bin/view/Documentation/save-concurrency



Posted By: Vonzkie
Date Posted: 15-Aug-2012 at 7:18pm
Hi,

So you mean to say there's no way in DomainModelTemplate or T4 Template that we can accomplish this?

Thanks,
Von


Posted By: mgood
Date Posted: 15-Aug-2012 at 7:51pm
Yes, that's what I'm saying. If you want to control domain model aspects such as concurrency detection from your code, you have to switch to Code-First.
 
http://drc.ideablade.com/xwiki/bin/view/Documentation/code-first - http://drc.ideablade.com/xwiki/bin/view/Documentation/code-first
 
With Code-First you can take care of such things very elegantly in a base class that all your entities extend from. The following is an example of such a base class that you can find demonstrated in the Cocktail Reference Application.
 
http://drc.ideablade.com/xwiki/bin/view/Documentation/cocktail-reference-application - http://drc.ideablade.com/xwiki/bin/view/Documentation/cocktail-reference-application
 
    [ProvideEntityAspect]
    [DataContract(IsReference = true)]
    [RequiresAuthentication]
    public abstract class EntityBase
    {
        private EntityFacts _entityFacts;
 
        [NotMapped]
        public EntityFacts EntityFacts
        {
            get { return _entityFacts ?? (_entityFacts = new EntityFacts(this)); }
        }
 
        [DataMember]
        [ConcurrencyCheck]
        [ConcurrencyStrategy(ConcurrencyStrategy.AutoIncrement)]
        public int RowVersion { getinternal set; }
 
        public virtual void Validate(VerifierResultCollection validationErrors)
        {
        }
 
        [BeforeSet]
        internal void RemoveWhiteSpace(IEntityPropertySetInterceptorArgs args)
        {
            if (args.EntityProperty.DataType != typeof(string) || args.Value ==  null)
                return;
 
            args.Value = ((string) args.Value).Trim();
        }
    }


Posted By: Vonzkie
Date Posted: 15-Aug-2012 at 8:38pm
Hi,

Thanks for the reply.

However we can't just simply convert our models to code first since our application are already up and running in the market.
So we have no choice but to do this manually in the designer..

Regards,
Von


Posted By: mgood
Date Posted: 15-Aug-2012 at 10:10pm
That's the perfect time to switch to Code-First :-) Kidding aside, yes you have a choice. Our T4 can generate Code-First style entity classes. We call this Code-Second.
 
http://drc.ideablade.com/xwiki/bin/view/Documentation/code-second -


Posted By: stephenmcd1
Date Posted: 16-Aug-2012 at 10:09am
Originally posted by Vonzkie

So we have no choice but to do this manually in the designer..

Don't forget that the designer is just a really fancy XML editor.  I've had times where I need to make lots of very similar changes and it was pretty easy using just a text editor and find/replace.  For example, in our app we have a column called Timestamp on almost every entity that is our concurrency column.  In the EDMX, there is a row like this under all our entities:
<Property Name="Timestamp" Type="Binary" Nullable="false" MaxLength="8" FixedLength="true" />
To add concurrency to all those properties we just did a search for that text and replaced it with this:
<Property Name="Timestamp" Type="Binary" Nullable="false" MaxLength="8" FixedLength="true" annotation:StoreGeneratedPattern="Computed" ib10:ConcurrencyStrategy="Client" ConcurrencyMode="Fixed" />
In no time, we added concurrency to hundreds of entities.  Of course, this is a one-time thing so for any new entities added to the model, you need to remember to set the concurrency.  But at least it saves time the first time. 

Note: Obviously you're case is a bit different - your column is called intConcurrencyID instead of Timestamp and you might want different options.  But if you just setup one property how you want it to look, you can then see what XML got generated for it and use that as a basis for the search/replace.

Hope that helps!

-Stephen


Posted By: Vonzkie
Date Posted: 16-Aug-2012 at 4:07pm
THanks guys for all the inputs. I'm gonna take note of using Code Second and this find-replace approach :)



Print Page | Close Window