David Hayden [MVP C#]

Sponsors

The Lounge

News

  • CodeBetter.Com Home

Other Links

Teas

Patterns & Practices

Florida .NET Developer

Book Reviews

Tampa ASP.NET MVC Developer Group

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
DLinq Example of External Mapping Support in May 2006 CTP

One of the new DLinq features in the May 2006 CTP is support for an External Mapping File. Included in the LINQ Preview is a document called, DLinq Overview for CSharp Developers, that includes a little overview of the feature.

Here is a snippet from the document:

- - - - - -

In addition to attribute-based mapping, DLinq now also supports external mapping. The most common form of external mapping is an XML file. Mapping files enable additional scenarios where separating mapping from code is desirable.

DataContext provides an additional constructor for supplying a MappingSource. One form of MappingSource is an XmlMappingSource that can be constructed from an XML mapping file. Here is an example of how mapping file can be used:

 

String path = @"C:\Mapping\NorthwindMapping.xml";
XmlMappingSource prodMapping = 
    XmlMappingSource.FromXml(File.ReadAllText(path));
Northwind db = new Northwind(
    @"Server=.\SQLExpress;Database=c:\Northwind\Northwnd.mdf",
    prodMapping
    );

- - - - - -

 

Dlinq Example Using XML External Mapping File

O/R Mappers like NHibernate, WilsonORMapper, etc. have made the use of an external mapping file so commonplace that I have pretty much embraced the idea of using external mapping files as opposed to attributes.

To test the functionality, I created a simple Test Database that includes 2 tables, States and Cities, as well as a quick LINQ Windows Application that includes 2 classes, State and City:

 

 

 

The code for the City and State Classes are as follows:

 

namespace DlinqDemo
{
    /// <summary>
    /// State
    /// </summary>
    public class State
    {
        private int _id;
        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private EntitySet<City> _cities =
            new EntitySet<City>();
        public  ICollection<City> Cities
        {
            get { return _cities; }
            set { this._cities.Assign(value); }
        }
    }
}

 

namespace DlinqDemo
{
    /// <summary>
    /// City
    /// </summary>
    public class City
    {
        private int _id;
        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        private int _stateId;
        public int StateId
        {
            get { return _stateId; }
            set { _stateId = value; }
        }

        private EntityRef<State> _state;    
        public State State
        {
            get { return this._state.Entity; }
            set { this._state.Entity = value; }
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }
}

 

External XML Mapping File

The relationship between the classes and database tables are described in the following XML File ( Mappings.xml ), which I had to create by hand. Unless I am mistaken, SqlMetal.exe will not create an XML Mapping File for you.

 

<Database Name="test">
  <Table Name="States">
    <Type Name="DlinqDemo.State">
      <Column Name="StateId" Member="ID"
        Storage="_id"
                DbType="Int NOT NULL IDENTITY"
        IsIdentity="True"
                IsAutoGen="True" />
      <Column Name="Name" Member="Name"
                Storage="_name"
        DbType="NVarChar(100) NOT NULL" />
      <Association Name="FK_Cities_States"
        Member="Cities"
                Storage="_cities" ThisKey="ID"
        OtherTable="Cities"
                OtherKey="StateId" IsParent="False" />
    </Type>
  </Table>
  <Table Name="Cities">
    <Type Name="DlinqDemo.City">
      <Column Name="CityId" Member="ID"
        Storage="_id"
                DbType="Int NOT NULL IDENTITY"
        IsIdentity="True"
                IsAutoGen="True" />
      <Column Name="StateId" Member="StateId"
                Storage="_stateId"
        DbType="int NOT NULL" />
      <Association Name="FK_Cities_States"
       Member="State"
       Storage="_state" ThisKey="StateId"
       OtherTable="States"
       OtherKey="ID" IsParent="True" />
      <Column Name="Name" Member="Name"
                Storage="_name"
        DbType="NVarChar(100) NOT NULL" />
    </Type>
  </Table>
</Database>

 

Strong Typing DataContext

Everything works through the DataContext Class. Per the documentation, it is much nicer to create a strongly typed version of it to keep things nice and neat:

 

namespace DlinqDemo
{
    /// <summary>
    /// Test
    /// </summary>
    public class Test : DataContext
    {
        public Table<State> States;
        public Table<City> Cities;

        public Test(string connection, MappingSource mapping)
                : base(connection, mapping) { }
    }
}

 

Test is an absolute horrible name. I just used the same name as the database, but a more descriptive and useful name would normally be in order.

 

Creating an Instance of the Test DataContext Class

I embedded the Mappings.xml file mentioned above into my windows application. The code to instantiate Test with the name of the connection string and XML Mapping File is:

 

XmlMappingSource mapping;

using (Stream  stream = Assembly.GetExecutingAssembly()
    .GetManifestResourceStream("DlinqDemo.Mappings.xml"))
{
    mapping = XmlMappingSource.FromStream(stream);
}

Test db = new Test("Data Source=.;Initial Catalog=test;Integrated Security=True", mapping);

 

You wouldn't hardcode your connection string like this, of course. If you don't want to embed your mapping file, you can pull it externally as shown in the code above from the documentation.

 

Querying

Now that one has an instance of the DataContext Class shown above, it is pretty easy to query for data:

 

** Get the state of Florida and city of Sarasota: **

 

State florida = db.States.Single(c => c.Name.Equals("Florida"));

City sarasota = db.Cities.Single(c => c.Name.Equals("Sarasota"));

 

** Get all the cities for Florida: **

 

ICollection<City> cities = florida.Cities;

 

** Append the number "2" to every city in Florida and save the changes back to the database: **

 

foreach (City city in cities)
{
    city.Name += "2";
}

db.SubmitChanges();

 

** Create a new city and save it to the database: **

 

City tampa = new City();
tampa.Name = "Tampa";
tampa.State = florida;

db.Cities.Add(tampa);
// or florida.Cities.Add(tampa);

db.SubmitChanges();

 

** Add a new state and city to the database: **

 

State georgia = new State();
georgia.Name = "Georgia";
db.States.Add(georgia);

City atlanta = new City();
atlanta.Name = "Atlanta";
atlanta.State = georgia;

georgia.Cities.Add(atlanta);

db.States.Add(georgia);

db.SubmitChanges();

 

Conclusion

I am still coming up to speed on LINQ and DLinq myself, so there may be ways to improve the code above. If you know of any, please let me know :)

 

Resources:

 


Posted 05-18-2006 3:22 PM by David Hayden

[Advertisement]

Comments

David Hayden wrote re: DLinq Example of External Mapping Support in May 2006 CTP
on 05-18-2006 4:34 PM
I just learned there is an option in SqlMetal.exe to generate an external mapping file. It is /map .
David Hayden - Florida .NET Developer - C# and SQL Server wrote DLinq Tutorial - Using External Mapping File and SqlMetal to Generate Classes and Mapping File
on 05-18-2006 7:56 PM
David Hayden - Florida .NET Developer - C# and SQL Server wrote DLinq Tutorial - Using External Mapping File and SqlMetal to Generate Classes and Mapping File
on 05-18-2006 7:57 PM
David Hayden wrote re: DLinq Example of External Mapping Support in May 2006 CTP
on 05-18-2006 7:59 PM
Here is another example that I just wrote which lets SqlMetal Generate the Class and XML Mapping File for me. Heck of a lot easier than doing it by hand:

http://davidhayden.com/blog/dave/archive/2006/05/18/2947.aspx
John Papa wrote re: DLinq Example of External Mapping Support in May 2006 CTP
on 05-20-2006 9:17 PM
Have u tried the dlinq designer in the may ctp?
David Hayden wrote re: DLinq Example of External Mapping Support in May 2006 CTP
on 05-21-2006 10:28 PM
I tried it this weekend for the first time. Very slick!

I tend to like external mapping, but since one has to decorate the entities with a number of other items to facilitate entity state tracking and synchronization, one might as well go the route of attributes in this case.

I'll have to do a part 2 on this tutorial, because although handcoding the mapping manually gives you a good feel for what needs to happen, I can't imagine ever doing it.
Christopher Steen wrote Link Listing - May 23, 2006
on 05-23-2006 10:35 PM

 A refresh button for asp.net pages [Via: pvanooijen ]
 ASP.NET 2.0 Fix That Everyone Needs [Via:...
Adnan Masood wrote re: DLinq Example of External Mapping Support in May 2006 CTP
on 05-28-2006 3:37 AM
Have you encountered any example of using .csv or XML data (not mapping) to be substituted as DLINQ data source instead of an MDF? There are examples available for XLINK but it doesn't support entire set of relational ops and are very "node specific".