visual-studiolinq-to-sqlsqlmetal

Different [DataMember] behaviour in sqlmetal than dbml designer


I've taken over an application using linq-to-sql and now plan to do some major changes to the database. Due to the lack of support for refreshing the model in the dbml designer I'm trying to use sqlmetal instead. However I've run into problems with the code generated by sqlmetal not being compatible with the colde generated by the dbml designer.

If I have a table (e.g. Car) which has an FK into another table (e.g. Model), then the serialization will differ, it will not generate a DataMember attribute for the association attribute:

// **************************
// *** Dbml designer code ***
// **************************

[ColumnAttribute(...)]
[DatamemberAttribute(...)]
public int ModelID
{
    // property get and set
}

[AssociationAttribute(...)]
[DataMemberAttribute(...)]
public Model Model
{
    // property get and set
}

// **********************
// *** Sqlmetal code ****
// **********************

[ColumnAttribute(...)]
[DatamemberAttribute(...)]
public int ModelID
{
    // property get and set
}

[AssociationAttribute(...)]
// No DataMember attribute 
public Model Model
{
    // property get and set
}

Is there a way around this, to get the Model property to be part of the data contract when using sqlmetal?


Solution

  • I ended up using a wrapper property:

    [DataMember(Name="Model", Order=100)]
    public Model ModelDataMember
    {
        get
        {
            return Model;
        }
        set
        {
            if(value != null)
            {
                Model = value;
            }
        }
    }
    

    First, I had problems on deserialization, when the client had set ModelID but not the Model reference. The SqlMetal generated code for the ModelID setter will throw an exception, if the Model reference have previously been set. This is handled by the Order property of the DataMember attribute, which ensures that ModelID is deserialized before Model.

    It still didn't work, because now on deserialization when the ModelID was set, but not the Model reference, the Model reference setter would zero out the ModelID. This behaviour is different compared to the dbml designer generated code, it is only SqlMetal that synchs the ModelID property with the Model property. The solution was to skip the stter if value is null.