Archive for January, 2008

ComboBox databinding for LINQ

January 17th, 2008

When you use the data context designer for LINQ to SQL, it will automatically use foreign-key relationships to build links between objects. Suppose you have an table called Address that has a column called CountryId which is a link into a Country table.
LINQ will create for you an Address object that contains an CountryId and an Country property. One of these is an integer value, the other is a Country object.
Here’s the important bit: once you have referenced the Country property you may not set the value of CountryId. If you do you will get a ForeignKeyReferenceAlreadyHasValueException exception thrown.
So, if you want to data bind a ComboBox you need to use the object property. In the above example you would set the ComboBox SelectedItem property to be _addressbindingSource – Country and the DisplayMember to be CountryName or whatever, and you would leave the ValueMember property blank.

Share

Many-Many Relationships in LINQ

January 9th, 2008

I’ve been playing around with LINQ a bit as a way of accessing SQL. The first major problem I’ve had is the lack of support for many-many relationships. There’s plenty of stuff around on the web about how to read many-many relationships but not so much on how to modify them.
The following example is something I’ve put together for my purposes – there’s no guarantee it’ll work for you.
The database has two tables Product and Section. There’s also a link table joining them together. I’ve used the designer in Visual Studio to create corresponding LINQ objects (note that you can only do this if your classes have a primary key. For the link table the best way to do this is to create a compound key across both columns).
I then created a partial class for Section to add the additional code for managing Product shown below:

///


/// Extensions to the LINQ Section class.
///

public partial class Section
{
private bool _suppressAdds;

protected EntitySet _products;

///


/// Handle the many-many link to products.
///

public EntitySet Products
{
get
{
_products = new EntitySet (onAddProduct, onRemoveProduct);

List productList = new List ();

foreach (var map in SectionProductMaps)
{
productList.Add(map.Product);
}

_suppressAdds = true;
try
{
_products.AddRange(productList);
}
finally
{
_suppressAdds = false;
}

return _products;
}
}

protected void onAddProduct(Product product)
{
if (!_suppressAdds)
{
SectionProductMap map = new SectionProductMap();
map.Section = this;
map.Product = product;

int count = (from maps in SectionProductMaps where maps.ProductId == product.ProductId select maps).
Count();

if (count == 0)
{
SectionProductMaps.Add(map);
DataContextFactory.DataContext.SectionProductMaps.InsertOnSubmit(map);
}
}
}

protected void onRemoveProduct(Product product)
{
// Find all entries for product in the section product map.
var toKill = from
map in SectionProductMaps.AsQueryable()
where
((map.ProductId == product.ProductId) && (map.SectionId == SectionId))
select map;

int c = toKill.Count();
DataContextFactory.DataContext.SectionProductMaps.DeleteAllOnSubmit(toKill);
}
}

And that’s it. I now have a Products property I can use as a collection of Products that manipulates the link table as required.

Share

Windows Server 2008: Hyper-V and Active Directory

January 7th, 2008

I’ve been playing around with release candidate for Windows Server 2008. Here’s a warning that might save you some time: you can’t use Hyper-V if your machine is configured as a domain controller. It won’t warn you – it’ll just blue screen when you try and start a VM.
MS are working on this, but don’t hold your breath waiting for a solution.

Share

Memory leaks and XML serialization

January 7th, 2008

I’ve recently been battling with a memory leak that only appears when the system is under heavy load. It turns out that the culprit is XML Serialization. Whenever a type is serialized for the first time, a custom C# class is created and compiled. Provided that you use the right constructor for XmlSerializer this class is supposed to be cached and reused.
Our problem turned out to be that the runtime keeps creating new serialization assemblies for the same type (only under heavy load). I proved this by writing a little application to capture invocations of csc, dump everything to log files and then invoke the real C# compiler so its clients continue to work as normal.
The workaround seems to be to use sgen to create serialization assemblies. That way the runtime should use the one you have prepared rather than writing a new one. There’s a great blog entry here http://www.kiwidude.com/blog/2007/02/vs2005-when-sgen-doesnt-work.html telling you how to do it.
Of course life isn’t quite that simple. The sgen build task doesn’t allow you to specify which types you want to serialize (although there are command line options for this) and by chance there are types in my file that won’t serialize to XML. Nevertheless I’m quietly confident this is going to work…

Share