Dailycode.info

Short solution for short problems

Entity framework and LINQ: load related tables

I was trying to load data coming from a linked table using a link table to manage the link records.
The entity diagram looks like this:
 
 
 
I’m using self-tracking entities. I’m loading the data from the Program table and need to know which transformants are associated with the program.
So here’s the LINQ code that I needed:
var list = from d in ents.Programs.Include("ProgramTransFormants.Transformants")
                       orderby d.Description
                       select d;
 
So with the linktablename.tablename the entity framework will load the child elements in one call.
 
 
 

Change the object graph or increase the MaxItemsInObjectGraph quota. '. Please see InnerException for more details.

When you start with WCF, you will certainly need to adjust the limits of the service. By default they are kind of low. So in my case we did. Especially the maxrecievedmessagesize.  

Setting up the service, configuring you’re limits and start to use. Sounds really great and simple. But sometimes when you are working with development data and start doing stress tests, you will encounter even more limits. One of these will generate this really nice error:

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetCountriesResult. The InnerException message was 'Maximum number of items that can be serialized or deserialized in an object graph is '65536'. Change the object graph or increase the MaxItemsInObjectGraph quota. '.  Please see InnerException for more details.

What this really means is that the number of objects send through the wire is higher than the default limit or the limit you have specified.  To send more large number of records (objects) over the wire you’ll need to adjust the following:

On the server (raise the maxitemsinobjectgraph):

 

<behaviors>
      <serviceBehaviors>
        <behavior>
          …
          <dataContractSerializer maxItemsInObjectGraph="10000000"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

 

 

On the client (raise the maxitemsinobjectgraph for the clients endpoint behavior):

 

<behaviors>
      <endpointBehaviors>
        <behavior >
          <dataContractSerializer maxItemsInObjectGraph="10000000"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>

 

 

The maximum size of the maxItemsInObjectGraph is: 2147483646.

Now you can get those long lists of data and sent it over the wire. Although I strongly believe you should reconsider when a lot of these exceptions occur and split up data in chunks or rethink the way the data is shown to the user.


Using a listview and the selecteditem with WPF and MVVM. (without touching the code behind)

The default listview by Microsoft for Wpf has no commands available. So how can we capture the selected event without using any of the code behind and still use the default controls by Microsoft.

The solution is this. We will bind the IsSelected property of the list to the IsSelected property of your data object.

<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />

 

If the data objects (Model) that are shown in the list do not have this property, we create a wrapper class the implement the IsSelected property.

One option is to create a partial class of your DTO or model to include the IsSelected property:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.Serialization;

 

namespace Regulatory.Server.DTO

{

    public partial class Country

    {

        public Country()

        {

            this.Created = DateTime.Now;

        }

 

        private bool _isSelected;

 

        [DataMember]

        public bool IsSelected

        {

            get { return _isSelected; }

            set { _isSelected = value; }

        }

    }

}

 

 

 

Last we capture the property changed event of the object and set the selected item in your view model to the model (wrapper class) that has the IsSelected property set to true:

CountryModel countryM = new CountryModel(country);

                countryV.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(countryM_PropertyChanged);

 

public CountryModel SelectedCountry

        { get; set; }

 

void countryM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)

        {

            string IsSelected = "IsSelected";

 

            // Make sure that the property name we're referencing is valid.

            // This is a debugging technique, and does not execute in a Release build.

            (sender as CountryModel).VerifyPropertyName(IsSelected);

 

            // When a audio record is selected or unselected, we must let the

            // world know that the TotalSelectedSales property has changed,

            // so that it will be queried again for a new value.

            if (e.PropertyName == IsSelected)

            {

                //We check if its a selected or unselected item.

                if (CountryList.Where(d => d.IsSelected == true).Contains(sender as CountryModel))

                {

                    //If its a selected item, set it as selected item in this class.

                    SelectedCountry = sender as CountryModel;

                }

            }

        }

 

Here you see no item is selected:

 

 

Next you will see that the CanSave and CanDelete react to the selecteditem changed:

 

 

 

public bool CanDeleteCountry

        {

            //Check if a country is selected.

            get { SelectedCountry != null; }

        }

 

 

 

 


The object cannot be deleted because it was not found in the ObjectStateManager

I was trying to delete an (state tracking) entity from the database. But when I called the deleteobject method, I got this nice error: The object cannot be deleted because it was not found in the ObjectStateManagerDescription: http://i1.social.s-msft.com/Forums/resources/images/trans.gif?cver=1864.689%0d%0a.

So after some googling around, I found this solution:

In stead of just deleting the object like this:

ents.TrialType.DeleteObject(type);

ents.SaveChanges();

 

I now first attacht the object and delete it afterwards:

ents.TrialType.Attach(type);

ents.TrialType.DeleteObject(type);

ents.SaveChanges();

 

Off course you can also just pass the ID of the object, retrieve the object from the entity context and delete it:

public void RemoveTrialType(string key)

{

    TrialType t = GetTrialTypeByID(key);

    try

    {

        ents.TrialType.DeleteObject(t);

        ents.SaveChanges();

    }

    catch (Exception)

    {

        throw new ArgumentException("Delete failed, not possible to delete record!");

    }

}


Entity framework and MS SQL database (identity insert)

Using the entity framework in combination with an existing MS SQL database, comes with some restrictions and sometimes you need to change the DB structure.

For example, when you start from an existing database and you use identities as primary keys, the entity framework won't like it. There are several things you can do, you can let the entity framework create the database, or you can switch for example to guids and insrt the guid yourself. Because MSSQL doesn't allow changing the primary keys, I just generated a table creation script, changed the primary keys to guids, dropped all tables and ran the scripts.

To erase tables quickly in MS SQL, use:

(Warning, the following script will delete all tables!!!!)

EXEC sp_MSforeachtable @command1 = "DROP TABLE ?"

This will delete all tables, then you can recreate the tables from a script you earlier created and alter the script as needed.


ContentPresenter and tabindex

When you are using contentpresenters to show some custom controls, then you will see that there is no TabIndex property available. Instead use this:

KeyboardNavigation.TabNavigation="Local"

KeyboardNavigation.TabIndex=0

So your contentpresenter could look like this:

<ContentPresenter Content="{Binding Path=AudioTypeVM}"

                        ContentTemplate="{StaticResource AudioTypeListTemplate}"

                        HorizontalAlignment="Left" VerticalAlignment="Stretch" Grid.Column="1" Grid.Row="4" Margin="15,3,0,0"

                        KeyboardNavigation.TabNavigation="Local"

                        KeyboardNavigation.TabIndex="5">

 </ContentPresenter>

Then do not forget to arrange the tabindex of your custom control. In my case it's a dropdown list and a button:

<UserControl x:Class="MyMediaControl.Controls.CaseList"

             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

             mc:Ignorable="d"

             d:DesignHeight="24" d:DesignWidth="267">

    <DockPanel Height="24" LastChildFill="True" Width="251">

        <ComboBox DockPanel.Dock="Left"  HorizontalAlignment="Left" Name="cmbCases" VerticalAlignment="Top" MinWidth="200" ItemsSource="{Binding CaseListSource}" DisplayMemberPath="CaseID" SelectedItem="{Binding SelectedCase}" TabIndex="0"/>

        <Button DockPanel.Dock="Right" Content="New"  HorizontalAlignment="Right" Name="btnNew" VerticalAlignment="Top" MinWidth="50" Command="{Binding NewCaseCommand}" TabIndex="1"/>

    </DockPanel>

</UserControl> 


Media control database version 1

I created a small WPF application that can handle all your hard copy media like CD's, DVD's, Blue ray, records, books etc.

It wil lhelp you keep track of things when you lend out media and find them.

See more of this here.

If you like to get the source code to see the WPF/MVVM code, no problem, simply contact me and I'll provide it.

Data is stored in XML. I used linq to query the data and WPF and MVVM to show the data.


Cannot get WCF hosting to work

 

We were trying to setup hosting outside of the visual studio internet web host. First tried it on the server, no problem. Then we tried it locally on our machine. I noticed that the IIS was not properly installed, so I installed it properly. Still the hosting was not working. It was giving a strange error this time:

Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral

Then I looked this up and discovered that the problem was that IIS was installed after the .Net Framework 4.0. This was giving problems especially for WCF services.

 

So the solution is simple, open the visual studio 2010 prompt and execute this command:

aspnet_regiis.exe –iru

 

This should solve your problem.

Solution found here.


Required field validation in WPF using MVVM

 

This article will describe simple validation handling for WPF and MVVM.

I first implemented input validation myself. This was OK, but the only down side was that the CanSave method of the relay command was not updated when I entered a value, only when I the field lost focus the update came and the Save button was enabled. This makes it hard to work if the Save button is the next action after filling in the value.

So I will discuss the implementation of the IDataErrorInfo interface. This actually will reflect in your Model, ViewModel and View. We will tell the View that ErrorHandling is done and that the property changed event will be the trigger to do the validation. Also, some styling is applied to visualize the error s. Then the Model will have to implement the actual validation sets telling the viewmodel whether the model is valid or not. Last the view model will have handle the actual save command and check the validation.

So let’s start from the bottom and work our way up. The model:

For the demo I used a simple popup screen that adds a record to the audio type list. The record consists of a name. This field we will use to implement the validation. An empty field is not allowed.

First implement the IDataErrorInfo interface to your class.

public class AudioTypeEnt: IDataErrorInfo

 

This  will expose 2 methods which we will use to handle the validation.

#region IDataErrorInfo Members

 

string IDataErrorInfo.Error { get { return null; } }
 
string IDataErrorInfo.this[string propertyName]
{
    get { return this.GetValidationError(propertyName); }
}
 
#endregion // IDataErrorInfo Members

 

Then we will need to explain what fields need to be validated and how:

string GetValidationError(string propertyName)

{

    if (Array.IndexOf(ValidatedProperties, propertyName) < 0)

        return null;

 

    string error = null;

 

    switch (propertyName)

    {

        case "Name":

            error = this.ValidateName();

            break;

 

        default:

            Debug.Fail("Unexpected property being validated on Audio Type: " + propertyName);

            break;

    }

 

    return error;

}

 

string ValidateName()

{

    if (IsStringMissing(this.Name))

    {

        return Strings.AudioTypeEnt_MissingName;

    }

    return null;

}

 

 

static bool IsStringMissing(string value)

{

    return

        String.IsNullOrEmpty(value) ||

        value.Trim() == String.Empty;

}

 

So here we checked if the Name property is not null or empty or has some spaces. If any of these, we will return the error string coming from a resource file telling that the name field is still missing entry.

Last what we need to implement in the model is the IsValid method. This will be called be the viewmodel to check the validity of the record.

/// <summary> 

/// Returns true if this object has no validation errors. 

/// </summary> 

public bool IsValid

{

    get

    {

        foreach (string property in ValidatedProperties)

            if (GetValidationError(property) != null)

                return false;

 

        return true;

    }

}

 

static readonly string[] ValidatedProperties =

{

    "Name"

};

 

So let’s move on to The view model. There we simply check the data and trigger a requery so the relaycommands can reflect this.  Also here the view model will have to implement the IDataErrorInfo

 interface:  public class AddAudioTypeViewModel : WorkspaceViewModel, IDataErrorInfo

 

#region Error Handling

 

public string Error

{

    get { return (AudioTypeRecord as IDataErrorInfo).Error; }

}

 

public string this[string propertyName]

{

    get

    {

        string error = null;

 

 

        error = (AudioTypeRecord as IDataErrorInfo)[propertyName];

 

        // Dirty the commands registered with CommandManager,

        // such as our Save command, so that they are queried

        // to see if they can execute now.

        CommandManager.InvalidateRequerySuggested();

 

        return error;

    }

}

 

#endregion

 

We implement the interface methods. You can do some extra validation here, but we just pass on the error and trigger the Requery by calling the CommandManager.InvalidateRequerySuggeted method.

Then we can tell the CanSave method what to check. And when a save is triggered we will again check if the record is valid, if so, just save it.

 

/// <summary>

/// Saves the audio to the repository.  This method is invoked by the SaveCommand.

/// </summary>

public void Save()

{

    if (!AudioTypeRecord.IsValid)

        throw new InvalidOperationException(Strings.AudioTypeEnt_MissingName);

    else

    {

/// Saves the audio to the repository

        GenericSingleton<RepositoryHold>.GetInstance().AudioRep.AddAudioTypeRec(new AudioTypeEnt() { Name = Name, Valid = true });

        base.OnPropertyChanged("DisplayName");

        RequestClose();

    }

}

 

/// <summary>

/// Returns true if the audio type is valid and can be saved.

/// </summary>

bool CanSave

{

    get { return AudioTypeRecord.IsValid; }

}

 

Last we have to tell the view that which field needs to be checked and what will trigger the validation check. This has to be done in the binding:

<TextBox Text="{Binding Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"

 

If you like, you can add a content presenter to show the errors that come from the view model:

<ContentPresenter

      Grid.Row="1" Grid.Column="1"

      Content="{Binding ElementName=txtName, Path=(Validation.Errors).CurrentItem}" Margin="10,0" />

 

Finally we define a template for the validation errors in the view:

<DataTemplate DataType="{x:Type ValidationError}">

                <TextBlock

          FontStyle="Italic"

          Foreground="Red"

          HorizontalAlignment="Left"

          Margin="0,1"

          Text="{Binding Path=ErrorContent}"

          />

 

And that should do it!

 

Nothing filled in:

After the first character is entered the save button is enabled: