Entity is currently read-only

Quick post on an issue that we were having today. This fix may just be a band-aid for another issue but this fix at least got us moving again today. Since I didn’t see anything concrete online for a solution I figured I would post this as a part one fix and then post a more detailed fix later.

We were getting this error earlier today in one of our projects that uses EF and WCF Ria Services.

This entity is currently read-only. One of the following conditions exist: a custom method has been invoked, a submit operation is in progress, or edit operations are not supported for the entity type.

The work around that we used for this is to simply do a check to see if the property is read only. Each entity has that property on it.

        private void SelectedInstitution_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (!_personDetailContext.CurrentPerson.IsReadOnly)
            {
                _personDetailContext.CurrentPerson.LastUpdatedDate = DateTime.Now;
            }
        }
We check to see if the CurrentPerson in this situation is readonly. If its not read only we go ahead and execute some other code. 
Again, this got us moving today, I am sure this is just step one in resolving this issue. 
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Combobox binding with different types

Binding to comboboxes in Silverlight has been an adventure the past couple of days. In our framework at ArchitectNow we use LookupGroups and LookupValues. In our database we would have a LookupGroup of NBA Teams for example. The group would be called NBATeams, we get the LookupGroupID and then get the values from the LookupValues table. So we would end up with a list of all 30+ teams. Our lookup values entity has a display text(string), value(string), IsActive and some other fields. With our applications we load all this information into the system when the user is logging in or right after they login. So in cache we have a list of groups and values that we can get at whenever we want to. We get this information in our framework simply by creating an observable collection of type LookupValue. To get a list of these values into our property all we have to do is.

var NBATeams = AppContext.Current.LookupSerivce.GetLookupValues(“NBATeams”);

Our combobox then is bound like this. (We use telerik components in most if not all our projects)

<telerik:RadComboBox ItemsSource="{Binding NBATeams}”></telerik:RadComboBox>

This should give you a list in your combobox.

We also set up another property in our ViewModel that is a just single object of NBATeams  - “SelectedNBATeam”

Our selectedItem in our combobox would look like, we would set this to a two way binding since we are sending data back.

SelectedItem={Binding SelectedNBATeam, mode=TwoWay}”

This is all pretty straight forward and we use this pattern throughout all our applications. What do you do though when you have a combobox in a ItemsControl or ListBox? Here we have a list of NBA Teams that are a string that are being brought back from the database. We cant have the selected item be our LookupValue because the data is a string and its being bound in an ItemsControl. In the example above we would just have the combobox in a form. Here though we have it in a ItemsControl, where there is no selected item from the initial ItemsSource.

In order to get the selected item to be displayed in the combobox you have to convert the LookupValue to a string. Then instead of using SelectedItem in the combobox use SelectedValue.

To convert the LookupValue we do this.

Create an observable collection of strings

public ObservableCollection<string> NBATeams { get; set;}

Then convert your lookups to strings

var NBATeams = new ObservableCollection<string>(AppContext.Current.LookupService.GetLookupValues(“NBATeams”).Select(x => x.DisplayText));

This will give us a list of strings and our selected value should be bound to the NBATeams property in our ItemsSource in our ItemsControl.

SelectedValue={Binding NBATeam, mode=TwoWay}”

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Silverlight Binding with multiple collections

We're designing some sport specific applications. In one of our views we have a gridview that is bound to an observable collection of Teams. This is pretty straight forward in terms of getting Teams bound to the GridView.

<telerik:RadGridView Grid.Row="0" Grid.Column="0" x:Name="UsersGrid" ItemsSource="{Binding TeamResults}" SelectedItem="{Binding SelectedTeam, Mode=TwoWay}">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn Header="Name/Group" DataMemberBinding="{Binding TeamName}" MinWidth="150"></telerik:GridViewDataColumn>
</telerik:RadGridView.Columns>
</telerik:RadGridView>

We use the observable collection of teams as our items source and then bind the property of TeamName to the first column. You can set the binding to mode=TwoWay, we use a dialog where we edit the selected item, so our binding here is not set to two way.

The issue comes when we want to bind to a property that has another collection in it. To continue on our code from above, we have an observable collection of teams, within that collection we have a collection of KeyPeople. We get this collection using RIA Serivces with the code below.

return _TeamsRepository.All().Include("KeyPerson");

Here we are getting all the teams and also including the KeyPerson entity. So when we are done with our Load we will end up with an observable collection of Teams with a navigation property / entity of KeyPerson. Within this KeyPerson entity is a list of people associated with that particular team. We want to display the head coach from this list of KeyPersons. This list currently has a list of ten or more people that are bound to this team, but we just want to display the Head Coach in the column next to team name.

The issue becomes how do we bind to this included entity? I have found about three different ways to solve this issue. The way that seemed to fit us best is to utilize the features within RIA Services. We can create client side properties that will do the work for us. We will create in the client side library a partial class of Team. We will end up in our library a file that is Team.shared.cs. The code below is what we will put into our partial team class.

        public KeyPerson Coach
        {
            get
            {
                if (this.KeyPerson != null && this.KeyPerson.Any())
                {

                   return this.KeyPerson.Where(x => x.RelationshipType == “HeadCoach”).FirstOrDefault(); 

                 }

                return null;
            }
        }

We will return just the person that is the Head Coach and then be able to bind that and any other additional properties that we need.

<telerik:GridViewDataColumn Header="Coach" DataMemberBinding="{Binding Coach.Name}" MinWidth="150"></telerik:GridViewDataColumn>

There are other ways that we could have solved this issue but we felt that creating a partial class through RIA Services best suited our needs.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

MSDN Search Help

Looks like MSDN has made a change to their search. If you navigate to

http://msdn.microsoft.com

You will see their search on the top of the page. If you put in a search term, Silverlight DataBinding

You will see results that are pulled from the forums of msdn, stackover flow and a few other places. You will also be able to see the number of replies to the thread and the threads that have been answered.

Great resource..

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Silverlight Relay Commands

I am fairly new at Silverlight development and I usually have an issue that needs research every day. Which I enjoy, since I like the idea of going into a day knowing that I am  going to learn something new. The issue that I am currently working on centers around relay commands. I have a pretty good handle on Relay Commands and how we use them within our applications.

<Button Command="{Binding ButtonCommand}" CommandParameter="NewRecruit" Content="New Recruit" />

Here in our xaml we have a button. The button has a Command and a CommandParameter. The command binds to the ButtonCommand that we have in our ViewModel

RelayCommand _buttonCommand;
        /// <summary>
        /// Gets the button command.
        /// </summary>
        /// <value>The button command.</value>
        public RelayCommand ButtonCommand
        {
            get
            {
                if (_buttonCommand == null)
                {
                    _buttonCommand = new RelayCommand(
                        x => x != null && x.ToString().Length > 0 && CheckCommandAvailable(x.ToString()),
                        x => ExecuteCommand(x.ToString()));
                }
                return _buttonCommand;
            }
        }

 

In our relay command we then do some checks with a lambda expression. We check if the command  parameter is null, is the length greater than 0 and we have a CheckCommandAvailable method that will tell  us if the button is even enabled. After we check on these three items we then pass the command parameter to an action method.

This is all pretty straight forward, the issue that we solved a few days ago centered around having a control that needed to use a Relay Command and this control was a nested control and was using a different DataContext. The example below illustrates how we handled this scenario.

In our xaml usercontrol we had to set a name to this control.

<Controls3:RadTileViewItem x:Class="RecruitStatusTileView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:Controls1="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls" 
    xmlns:Controls2="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Input" 
    xmlns:Controls3="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation" 
    mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="800" Header="{Binding Title,Mode=TwoWay}" MinimizedHeight="100" 
                           x:Name="StatusView">

Here we are using a telerik RadTileViewItem. We set the name of this control to “StatusView”. In our button control we set our command parameters and commands different than the example above.

<HyperlinkButton Content="{Binding BigBoardButtonText, Mode=TwoWay}" CommandParameter="{Binding 'Position.PositionName'}" Command="{Binding ElementName=StatusView, Path=DataContext.BigBoardCommand, Mode=TwoWay}" />

This hyperlink button lives in a ListBox control and this listbox has an ItemSource of PositionSelectors. The Command Parameter is binding to the Position.Position property of that PositionSelectors object. This again is pretty straight forward again. What gets a bit tricky is the Command property in the hyperlink. It is binding to the element name we created in the user control (StatusView) Because this hyperlink is in a listbox and is in the item template it doesn’t have a direct handle on the DataContext that the RadTileViewItem has so we have to make sure it does. We do that by binding to the element name of status view then set the path to DataContext.BigBoardCommand. BigBoardCommand is the name of the RelayCommand in the view model.

private RelayCommand _bigBoardCommand = null;
        /// <summary>
        /// Gets the big board command.
        /// </summary>
        /// <value>The big board command.</value>
        public RelayCommand BigBoardCommand
        {
            get
            {
                if (_bigBoardCommand == null)
                {
                    _bigBoardCommand = new RelayCommand(x => true, x => AddToBigBoard(x.ToString()));
                }
                return _bigBoardCommand;
            }
        }

From there we check for true again and then call the action and pass in the parameter that we had as the command parameter.

What we are working on now is a bit trickier than this second example. In the above example we are only creating this TileViewItem with this name “StatusView” once. In another part of our application we are generating multiple TileViewItems, so we cannot set the name in the control as we cant have multiple controls with the same name. When we run the application we get an error that reads that the value is out of expected range. My searching has led me to think we cannot have multiple controls with the same name.

This is today’s problem and Ill post the solution to this once it is found.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

MVVM Properties with Resharper

Read this early this morning and it is simple since we have all probably put together a code snippet. With the projects that we do at ArchitectNow we write alot of new custom views and view models, which results in having to write repetitive property code. We changed the context of the code a bit to suit our infrastructure but the idea is to have these properties created quickly.

thanks to sparky dasrath for reminding us how easy this is to do

sdasrath.blogspot.com/2011/02/20110221-resharper-c-snippet-for-mvvm.html

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Entity Framework - When using table joins

When you are working with join tables there are a few things that have to be done in order to get a handle on the necessary properties.

First, when you have a join table with no payload(meaning that only two columns show up in the model, ex: UserID and GroupID) these entities will not show up in the edmx. In our example the user table will show a navigation property to the Group entity, and the Group entity will show a navigation property to the User entity

Even though those navigation properties show up and you feel that you will have a handle on them you will not.

You will be unable to do this

User _user = new User();

_User.Groups.....

If you have other entities that do not work off of join tables then you will be able to do this

User _user = new User();

_user.Program

Because there is a join table there is some additional work that has to be done in order to get a handle on this navigation property.

Step 1: In the domain context class you have to change your calling method to "include" the entity that you are looking to get a handle on.

 public IQueryable<User> GetUsersByProgramID(int programID)
        {
            return _userRepository.All().Where(x => x.ProgramID == programID).Include("Groups");
        }

at the end of this method we are using the .Include("Groups") on the GetUserByProgramID

Step 2: in the domain context metadata you have to set some attributes on the groups property.

            [Include]
            [Association("Groups""UserID""GroupID")]
            public EntityCollection<Group> Groups
            {
                get;
                set;
            }

this is the internal sealed class UserMetadata -

we have to set up the association - within that is the name of the entity and the two columns in the join table.

 

another note - anytime that you are using an include  you should go into the metadata class and set that property to [Include] - you dont have to set the [Association] unless you are using a join table.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati
Twitter