Linq To SQL Tutorial – Set inheritance modifiers with SQLMetal

8

Posted by Joe | Posted in C#, Linq | Posted on 01-07-2009

I have created an base class which my entities inherit from that gives a property called IsNew which returns true if the the value of ID is 0; all of my tables use ID for the identifier.

 

public abstract class EntityBase
{
    public virtual int ID { get; set; }

    public bool IsNew
    {
        get
        {
            return ID == 0;
        }
    }
}

For this to work each of my entities need to use the override modifier for the ID property.  Using the O/R Designer it is possible to set the inheritance modifier for each property, but this is not possible using SQLMetal and I need to use SQLMetal to set the base class.

To overcome this I have a batch file that first creates my .dbml file using SQLMetal:

SQLMetal.exe /server:localhost /database:University /dbml:University.dbml /namespace:Entities /context:UniversityDataContext /pluralize

I then run a console application to find column nodes with the name of ID, and add the Modifier attribute:

EntityProcessor.exe University.dbml

The code for EntityProcessor looks like this:

 

static void Main(string[] args)
{
    try
    {
        //Ensure there is an argument for the DBML file
        if (args.Count() == 0)
        {
            throw new ApplicationException("DBML path expected.");
        }

        string dbml = args[0];

        //Load the DBML file
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(dbml);

        //Loop through the tables
        foreach (XmlNode node in xmlDoc.GetElementsByTagName("Table"))
        {
            //Loop through the nodes for the type
            foreach (XmlNode child in node.FirstChild.ChildNodes)
            {
                //Find the ID column node
                if (child.Name.Equals("Column") && child.Attributes["Name"].Value.Equals("ID"))
                {
                    //Create the modifier attribute to add to ID column
                    XmlAttribute modifierAttribute = xmlDoc.CreateAttribute("Modifier");
                    modifierAttribute.Value = "Override";
                    child.Attributes.Append(modifierAttribute);
                }
            }
        }

        //Save the updated DBML file
        xmlDoc.Save(dbml);

        Console.WriteLine("Processing complete");
    }
    catch (Exception ex)
    {
        Console.WriteLine("An error occured: {0}", ex.Message);
    }
}

Finally I use SQLMetal again to create my entities from the updated .dbml file:

SQLMetal.exe /code:University.cs /entitybase:EntityBase /namespace:Entities University.dbml

My new entities now have an ID property with an overrides modifier that looks like this:

[Column(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public override int ID
{
    get
    {
        return this._ID;
    }
    set
    {
        if ((this._ID != value))
        {
            this.OnIDChanging(value);
            this.SendPropertyChanging();
            this._ID = value;
            this.SendPropertyChanged("ID");
            this.OnIDChanged();
        }
    }
}

I can now call IsNew on any of my entities to check if they have been inserted into the database.

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Comments (8)

This post as well as most of the others have been extremely helpful to me. You have really been a big help. I was wondering however if there was a way to accomplish the EntityBase class without modifying the dbml file with your console application. My boss is having a problem with this.

Thanks so much.

Hi Michael

The console application it just to easily recreate the model after making changes to the database.

If you don’t want to use SQLMetal you can set inheritance modifiers from the properties window for the DBML file.

Cheers

I think the isnew is a cool feature and being able to set the dbml file to create entities which overrided properties from a base class is way cool. I wish you would help me …. see previous post :(

Hi Roberto

I don’t seem to have a previous comment from you, what is the problem?

Joe

Joe, I thought you might find this method for creating the base class helpful. I have not tried it, but I have seen this idea used in more then one place. http://www.davidturvey.com/blog/index.php/tag/linq-to-sql/

Take care

In case your interested, I found another way to accomplish this without setting the inheritance modifiers via your console app (which is very cool by the way) or via the properties window. I changed the BaseEntity to an interface instead of an abstract class. This provided the same functionality with a little less work on my part. Less work means less opportunity to make a mistake.

Thanks for all the articles. They have really been a big help to me.

Glad you found them helpful Michael

Joe

Michael how were you able to turn the Entitybase to an interface when you have the IsNew method which seems to me, would have to exist outside of an interface.

Write a comment