May 21, 2010

Entity Framework 4 : Cascaded Delete in Parent-Child Relationship?

Extending the previous post, let’s look at cascaded delete

image

[TestMethod]

[ExpectedException(typeof(System.Data.ObjectNotFoundException))]

public void DeleteParentEntity_WithOneToOneChildEntityRelationshipConstraint_ChildIsAutomaticallyDeleted()

{

    // save parent and child (1:1)

    FinanceMinister financeMinister = new FinanceMinister

    {

        Name = "Giulio Tremonti",

        Email = "gt@finanze.it"

    };

    Country country = new Country

    {

        Name = "Italy",

        GDP = 2118.264M, // billions ?

        ForeignDebt = 0M,

        FinanceMinister = financeMinister

    };

    this.target.Add(country);

    this.target.Save();

    int financeMinisterId = financeMinister.Id;

 

    // check if that was done right

    Country reloadedCountry = this.target.GetById<Country>(new Country { Id = country.Id });

    Assert.AreEqual<string>(country.FinanceMinister.Name, reloadedCountry.FinanceMinister.Name);

 

    // delete Country and check that treasurer is also gone

    this.target.Delete(country);

    this.target.Save();

    this.target.GetById<FinanceMinister>(new FinanceMinister { Id = financeMinisterId });

}

throws

image

Now setting the relationship to “cascade”

image

Runs OK, deleting the country and the corresponding finance minister in one go:

image

image

Entity Framework 4 : Delete child from ParentChild Relationship – throws or what?

[topic from a discussion; addressing a colleague]

Imagine the very common situation where you have a parent-child relationship like the following, and you want to delete the child (Currency; or better just remove the relation by setting the parent’s child navigation property to null):

image

Having code (show in an intergration test) like this

[TestMethod]

public void RemoveChildEntityNavigationFromParentEntityProperty_WithManyToOneConstraint_Throws()

{

    // save parent and child with a 1:* relationship constraint

    int dbGeneratedCityId = -1;

    Currency chf = new Currency { Symbol = "CHF", Name = "Schweizer Franken" };

    City city = new City { Code = "ZRH", Name = "Zürich", Currency = chf };

    this.target.Add(city);

    this.target.Save();

    dbGeneratedCityId = city.Id;

 

    // get the parent again from the database and get rid of the child

    City reloadedCity = this.target.GetById<City>(new City { Id = dbGeneratedCityId });

    Assert.IsNotNull(reloadedCity.Currency);

    reloadedCity.Currency = null;

    this.target.Save();

 

    // assert that the child was properly deleted

    City reloadedUpdatedCity = this.target.GetById<City>(new City { Id = dbGeneratedCityId });

    Assert.IsNull(reloadedUpdatedCity.Currency);

}

 

Using SQLProfiler shows that the following queries are emitted for the first code block

image  image

Calling Save() in the second block throws the following exception:

image

Aha, sure, this is due to the “1” in the “1:*” relationship – no cities without a default local currency (not even south european EU contries … sorry, no, not funny).

Let’s change this to “0..1”

image

Running the same test again shows “green”

image

emitting the Update statement.

image

Please note:

  • depending on the constraint, there may be no Delete(chf) necessary
  • relationship constraints violations throw exceptions
  • simply set the parent’s child navigation property to null
  • loosening the constraint to “0..1” leaves the child entity in the database

In comparison we can do the following (with “0..1” relationship):

[TestMethod]

public void DeleteChildEntityFromParent_WithManyToOneConstraint_Throws()

{

    // save parent and child with a 0..1:* relationship constraint

    int dbGeneratedCityId = -1;

    Currency euro = new Currency { Symbol = "EUR", Name = "Euro" };

    City city = new City { Code = "ATH", Name = "Athens", Currency = euro };

    this.target.Add(city);

    this.target.Save();

    dbGeneratedCityId = city.Id;

 

    // get the parent again from the database and get rid of the child

    City reloadedCity = this.target.GetById<City>(new City { Id = dbGeneratedCityId });

    Assert.IsNotNull(reloadedCity.Currency);

   this.target.Delete(reloadedCity.Currency);  // Athens and no more Euro

    this.target.Save();

 

    // assert that the child was properly deleted

    City reloadedUpdatedCity = this.target.GetById<City>(new City { Id = dbGeneratedCityId });

    Assert.IsNull(reloadedUpdatedCity.Currency);

}

and get

image

Setting the constraint back to “1:*” throws too:

DeleteChildEntityFromParent_WithManyToOneConstraint_Throws threw exception:
System.Data.UpdateException: A relationship from the 'CityCurrency' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'City' must also in the 'Deleted' state.

Guessing the same behavior for NHibernate. Can anybody confirm this?

May 17, 2010

Public Interfaces of WCF in Silverlight 4

Microsoft seems to have added some more interfaces to System.ServiceModel in Silverlight 4 (came across a blog post from Dominick Baier). These can be used as WCF extensibility points.

Here is a list of all the public interfaces I found reflecting the assembly:

System.ServiceModel.IDefaultCommunicationTimeouts
System.ServiceModel.ICommunicationObject
System.ServiceModel.Channels.IChannel
System.ServiceModel.Channels.IChannelFactory
System.ServiceModel.Channels.IChannelFactory`1[TChannel]
System.ServiceModel.Channels.IInputChannel
System.ServiceModel.Channels.IOutputChannel
System.ServiceModel.Channels.IDuplexChannel
System.ServiceModel.Channels.ISession
System.ServiceModel.Channels.IInputSession
System.ServiceModel.Channels.IOutputSession
System.ServiceModel.Channels.IDuplexSession
System.ServiceModel.Channels.ISessionChannel`1[TSession]
System.ServiceModel.Channels.IDuplexSessionChannel
System.ServiceModel.Channels.IInputSessionChannel
System.ServiceModel.Channels.IOutputSessionChannel
System.ServiceModel.Channels.IRequestChannel
System.ServiceModel.Channels.IRequestSessionChannel
System.ServiceModel.Channels.IHttpCookieContainerManager
System.ServiceModel.Description.IEndpointBehavior
System.ServiceModel.IExtensionCollection`1[T]
System.ServiceModel.Description.IContractBehavior
System.ServiceModel.IExtensibleObject`1[T]
System.ServiceModel.IExtension`1[T]
System.ServiceModel.Description.IOperationBehavior
System.ServiceModel.IContextChannel
System.ServiceModel.IClientChannel
System.ServiceModel.Dispatcher.IClientOperationSelector
System.ServiceModel.Dispatcher.IParameterInspector
System.ServiceModel.Dispatcher.IClientMessageFormatter

System.ServiceModel.Dispatcher.IClientMessageInspector
System.ServiceModel.Dispatcher.IDispatchMessageFormatter

System.ServiceModel.Channels.IMessageProperty

generated (without Reflector) using

IList<Type> types = typeof(IClientMessageInspector).Assembly

    .GetTypes()

    .Where(t => t.IsInterface && t.IsPublic)

    .ToList();

 

I have not tried them, but the bold ones are interesting for WCF extensibility.

May 3, 2010

Exclude from Code Coverage (Visual Studio 2010)

 

I was working on a library that adds some customer specific functionality to web services and WCF. I decided to have it very highly covered by unit tests. Unfortunately there is some static functionality in WCF (OperationContext) that is hard to be used in unit tests (it throws). So I wrapped this code behind a custom C# interface with a production implementation calling OperationContext and an (independant and fast) unit test implementation/mock. The small and simple production implementation had some negative impact on Visual Studio (instruction) code coverage (being below 100%). I figured out how to exclude this piece of code.

The way to do this is to add the [ExcludeFromCodeCoverage] attribute to class, property, method or event:

namespace MyTrials

{

    // [ExcludeFromCodeCoverage]

    public class NotCoveredClass

    {

        [ExcludeFromCodeCoverage]

        public string NotCoveredProperty { get; set; }

        public string CoveredProperty { get; set; }

 

        [ExcludeFromCodeCoverage]

        public EventHandler<EventArgs> OnNotCoveredEvent { get; set; }

        public EventHandler<EventArgs> OnCoveredEvent { get; set; }

 

        [ExcludeFromCodeCoverage]

        public void NotCoveredMethod()

        {

        }

 

        public void CoveredMethod()

        {

        }

    }

 

    public class CoveredClass

    {

    }

}

Write some more useful unit tests than I did for this post:

[TestMethod]

public void CodeCoverage_ExcludeWith_ExcludeFromCodeCoverage_FromClassMethodPropertyEvent()

{

    CoveredClass target = new CoveredClass();

    NotCoveredClass target2 = new NotCoveredClass();

 

    target2.CoveredMethod();

}

 

to have it excluded:

image

Other ways I’ve seem were to add [System.Diagnostics.DebuggerHidden] or [System.Diagnostics.DebuggerNonUserCode] to methods – but with some side effects!