Uncategorized

JQuery Input Field Magic

I’m working on a form that takes in names of children to be added as visitors to an organization. The form has 20 rows of input fields enclosed in a TBODY, so I know which rows are not header rows. I don’t want to show all 20 rows, since most people have on average three children, but I want to be able to handle a large group of children in a family, in case the Duggars move here or something. So, the following javascript hides all fields except the first and except any that are pre-filled (in the event that form validation fails).


<script type="text/javascript">

var $children = $("#children");
$children.find("tbody tr:not(:first):not(:has(input[value]))").hide();
$children.append("

");
$("#addChild").click(function () {
var nextrow = $children.find("tbody tr:hidden:first")[0];
$(nextrow).show();
nextrow = $children.find("tbody tr:hidden:first")[0];
if (nextrow == null) {
// get rid of add button since there are no more hidden rows to display
$("#addChild").remove();
}
});

</script>

Let’s look at this line:

$children.find("tbody tr:not(:first):not(:has(input[value]))").hide();

I’m basically saying, find all TR (table rows) inside of a TBODY tag, excluding the first and excluding any rows that contain INPUT tags that contain a value.

The next line adds a TFOOT tag to the end of the table, and adds a button inside a row called addChild.

The next code block acts when the button is clicked. It finds the next hidden row, and displays it. It then finds the next hidden row after that, and if one is not found, the button is removed.

Uncategorized

My gripes with the Facebook iPhone app

I use the Facebook iPhone app all the time, far more than I use the web site. The app is great, except for a couple flaws, one which I think is a major issue.

There is no way to block posts from other people like you can with the web site. I had this group “liked” called No Stressss, which had some cool stuff occasionally, but most of the time posts were made in Arabic and there would be 10 posts in a row, as if the person was copying-and-pasting and posting stuff rapid-fire. I blocked their posts from the web site, but they still show up on my phone, since the phone app doesn’t seem to follow the same post display rules as the web site does. Since I use Facebook on my phone more than I do the regular web site, I had to “unlike” them so the barrage of posts didn’t show up on my phone anymore. I didn’t understand how to unlike someone at first, especially since I wasn’t able to see their posts on the web site and you can’t hide posts from people from the phone app, so I had to type the name of the person and find the tiny “unlike” link on the left side to remove them.

That’s no so bad, I guess. There should be a way to block posts and like/unlike people from the phone. That’s not the most annoying issue though… I’ll read Facebook once or twice a day, at most. The way the news feed on the phone is set up is you scroll up and down a “page” of posts. If you pull the list down (scroll up) and then let go, you will refresh the list of posts. If you scroll to the bottom, there is a “Older Posts” button that, when clicked, loads the next page of results and appends it. Super simple, great UI design, and a three year old can figure it out. My gripe is with how arriving posts are handled. It seems the app either polls for new posts on a timer, or there’s a push notification sent when a new post has been posted. If you’re three pages deep, the app’s UI will block/freeze and the list will completely reset to the first page of posts. So, I’m reading a post from my cousin about fist pumping to Jersey Shore and just when I’m about to hit the reply button to call him a dirty little hamster, the UI blocks and the list resets about 5 seconds later.

Why does the list have to reset itself? Basically the list is a collection of posts ordered by date and time descending. Since it’s either polling for new posts or using a push notification to get new posts, why not just push the new results to the top of the stack rather than reset the whole list, so I don’t have to scroll down to the bottom of the list and click Older Posts three times to get back to where I was? If I close and re-open the app, the list can be reset then. I wouldn’t reset the list if the person closed or backgrounded the app within a few minutes.

The Facebook app is indispensable, and aside from these issues, is well designed. It just needs a little more polish to achieve greatness.

Summary:

Posts on phone do not adhere to ignore rules set up on the web site.
There is no way to block posts, or unlike people from the phone app.
When new posts arrive, the list resets itself to the first page, losing your current place.

C#, Generics, XAML

Binding to a Checkbox List in XAML

This technique is useful outside of XAML bindings, too. I found myself working with a person object that can belong to 0 or more groups. The database spec is that it is a many-to-many relationship, something that RIA services chokes on at this time.

Group
- ID
- GroupName
- GroupDescription

Person
- ID
- FirstName
- LastName

PersonXGroup
- PersonID
- GroupID
- CreationTimeStamp // this is here because RIA doesn't play nice with *-* relationships

So, imagine here that there are two foreign keys set up on this model, you know where they go. You need to bind to two different things: The master list which contains all available groups, and the groups that this person has enabled. So, how would you go about binding this list to an ItemsControl filled with checkboxes that allow you to update the state? Use a CheckboxBinder object, which follows.


///

/// Given a master list of items and an object containing a subset of these items,
/// such as a list of groups available and a person belonging to none, some, or all groups,
/// this class allows for binding this list to an itemscontrol with checkboxes to
/// turn on/off items by adding or removing the groups from the person.
/// Adding and removing the items once chnages are to be committed can be handled
/// in a couple ways: (a) By hand, looping through the collection and adding or removing
/// each one, using HasChanged() to see what items have changed, or
/// (b) assign a delegate action for the work to be done when the state changes.
///

///
public class CheckboxBinder
{

public T Item { get; set; }

///

/// Gets or sets the current checked state for this item.
/// If the ItemCheckedChanged delegate is not null, it is called when the state of the item
/// changes.
///

public bool IsChecked {
get { return _isChecked; }
set {
if (_isChecked != value) {
_isChecked = value;
if (ItemCheckedChanged != null) { ItemCheckedChanged(Item, IsChecked); }
}
}
}
private bool _isChecked;

///

/// Optional delegate that is called when IsChecked has changed.
/// Returns the item and its current check state.
///

public Action ItemCheckedChanged { get; set; }

//////////////////////////////////////////////////////

private bool InitiallyChecked { get; set; }

//////////////////////////////////////////////////////

public CheckboxBinder(T item, bool initiallyChecked) {
Item = item;
_isChecked = initiallyChecked;
InitiallyChecked = initiallyChecked;
}

public bool HasChanged() {
return (IsChecked != InitiallyChecked);
}

}

It’s a small class with a lot of power. On your viewmodel (you are using viewmodels, right?) define a collection of ObservableCollection<CheckboxBinder>. This is what you bind your ItemsControl to in your XAML code.

public ObservableCollection<CheckboxBinder> Groups { get; private set; }

When a Person object has been loaded for editing, I populate this list. The constructor for the CheckboxBinder object requires an instance of the item to be bound to, and the initial state as a boolean. The current state of the object is controlled by a bool property called HasChanges(), which compares the initial state to the current state. However, that would be used in a scenario where, when you press the Save button, your code would loop through the entries or use a LINQ statement to grab everything that has changes and then perform an action on it. However, that breaks up the functionality into multiple places throughout your code file, so I enabled another method of updating the collection with the use of an Action property called ItemCheckChanged:

///

/// Handles loading the groups and performing any changes, using the CheckboxBinder's
/// provided change delegate.
///

private void loadGroups() {
Groups = new ObservableCollection<CheckboxBinder>();
foreach (Group group in Reference.PersonData.Groups) {
var cbgroup = new CheckboxBinder(group, CurrentPerson.PersonXGroups.Any(g => g.Group == group));
cbgroup.ItemCheckedChanged = (item, isChecked) => {
if (isChecked) {
CurrentPerson.PersonXGroups.Add(new PersonXGroup() { Group = item, Person = CurrentPerson });
} else {
PersonXGroup pxg = CurrentPerson.PersonXGroups.Single(px => px.Group == item);
//CurrentPerson.PersonXGroups.Remove(pxg);
Reference.PersonData.Delete(pxg);
}
};
Groups.Add(cbgroup);
}
}

You pass ItemCheckedChanged a void delegate with 2 parameters: The item being modified and its current state. It’s only called when the value actually changes (so if the current state is false and you change the value to false, this will not be called). The update code handles adding and removing items from the collection.

if (isChecked) {
CurrentPerson.PersonXGroups.Add(new PersonXGroup() { Group = item, Person = CurrentPerson });
} else {
PersonXGroup pxg = CurrentPerson.PersonXGroups.Single(px => px.Group == item);
//CurrentPerson.PersonXGroups.Remove(pxg);
Reference.PersonData.Delete(pxg);
}

This way, you’re not iterating through a loop at the start of your Save routine. However, this is possible because I can just RejectChanges on my data context if I so desire – but the other aforementioned method works well if you don’t have the ability to roll back changes like you can on a data context.

Here’s the XAML used to bind to the checkbox list:
<sdk:Label Content="Groups" Style="{StaticResource FormHeaderStyle}" Margin="5,10,5,0" />
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Path=Groups}" Height="130">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Margin="2" Content="{Binding Path=Item.GroupName}" ToolTipService.ToolTip="{Binding Path=Item.GroupDescription}" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>

Has this helped you? Do you know of a better way to accomplish the same task? Shout it out in the comments.

Uncategorized

Building infrastructure to support one declaration of domain model for use with EF and RIA Services

I’ve been working on a way to declare a domain model on the server, to be used on both the server and on the Silverlight client through RIA services. Believe me when I say that this has been no easy task!

I tried to implement a single shared IDataRepository interface to both the client and server by marking the filename as .shared.cs. The data access methods would use a syntax similar to the following: repo.Get(string[] includeRelatedTables, Action<IQueryable> results), so when the data has been retrieved, it calls the callback with the results. With Silverlight, there is no synchronous database communication, so this syntax is the only one that works. However, that callback method won’t work when using the domain model with MVC… I can’t return a ViewResult to the anonymous function inside.

Another way of doing this would be to declare virtual methods that, on each side (client EF/server RIA) implements its own way of getting the data. Another better solution would be to declare these functions as Func<IQueryable> properties that can be get or set. However, I would run into the same problem as MVC on the server side, where the virtual method or Func would require me to return the results from the data source, and I can’t return from within an anonymous function… so, with this method, I’ve hit a brick wall.

I guess it’s time to install the Async CTP and see if I can make this work without using callbacks. I know projects like CSLA have this covered, but I want to create (or find a good) solution that works right away with my EF entities and RIA entities. The Async CTP should allow me to write my async data call methods like I would with RIA services, so I should be able to get rid of all of the callbacks and have both interfaces return the list of objects directly.

C#, Silverlight

Silverlight and Asynchronous Calls

LOL, people still whine about having to do everything asynchronously in Silverlight. When I dove into Silverlight head-first around September, I didn’t know much about asynchronous calls, besides the usual BeginInvoke() calls for long running threads. Needing to use async calls for all data transfers was a bit daunting. For a long time, I tried making all calls synchronous using the dispatcher, wait loops… most anything I could think of. However, I have found that learning async patterns has made me a better programmer, and I would use the async calling model even if I was in desktop WPF/WinForms and had the sync model available to me.

The project I am working on for Morris Consulting (I’m on an NDA, so I can’t go into details) has a list of people represented by buttons whose states can be turned on and off. When I first started to work on the project, I was using all “faked” synchronous calls to get the data. I noticed that the SL app would stall for three seconds while loading all 1000+ people into a custom usercontrol I made. Three seconds is bad, but it’s not horrible, I told myself. But, what if the list was composed of 50,000 people? I would be looking at a pause of two and a half minutes, which is very unacceptable!

Firstly, use the MVVM pattern. Setting up a viewmodel to handle the workload, rather than cowboy-coding it into the UI, is super-beneficial in the long run. It’s testable, and you can use the viewmodel in SL, WPF, WinForms, MVC, or whatever UI you want. You could even use a string tokenizer to take input and make a console app that runs your program. You only have to write your business rules one time, and your different UIs will consume your view model. Mind you, writing a clean, well thought out UI only seems easy, but in some aspects can be harder than writing the business logic! You don’t want to repeat yourself at all, so it’s important you separate your business logic from the UI for any medium to large application.

Your viewmodel should not rely on the UI at all, so no dependency properties should be on it. Use regular properties and INotifyPropertyChanged, and then any XAML binding (or WinForms binding, shudder) won’t have any issues. DO make a base ViewModel class that is used by your view models. DO make a view model that is used by a single view. I’ve used a single view model that is used by a couple views, but I make a copy of it once one of the views needs major changes that could break the first view. Your view models should implement INotifyPropertyChanged for binding notifications, IDisposable if you have resources that need to be released when you dispose of the view model (also allowing you to use the “using” statement), IDataErrorInfo optionally if you have extra data in the view model that needs to be validated.

If you’re using RIA services, you can mark the view models as .shared.cs so they are shared by the client also! I’ll write more on this soon.

Uncategorized

Attribute for validating when at least one of many properties must be set

Here’s some code for a validation attribute that can be set on a class, when at least one property out of a couple must be set in order to pass validation. A great use for this is when you require either a home phone number or a cell phone number to be set, since you can’t expect all user to have a home phone number, and you can’t expect all users to have a cell phone number either, but you have to know whether it is a home or a cell number.

Enjoy!

///

/// Checks all the properties and returns true if at least one has a value.
/// ErrorMessage string must be specified!
///

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class MustHaveAtLeastOneOf : ValidationAttribute
{
private readonly object _typeId = new object();

public MustHaveAtLeastOneOf(params string[] properties)
: base("") {
MustHaveAtLeastOneOfProperties = properties;
}

public string[] MustHaveAtLeastOneOfProperties { get; private set; }

public override object TypeId {
get {
return _typeId;
}
}

public override string FormatErrorMessage(string name) {
return ErrorMessageString;
}

public override bool IsValid(object value) {
if (ErrorMessageString == null) { throw new ArgumentNullException("ErrorMessage string must be filled in when declaring the attribute."); }
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
//object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value);
//object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value);
//return Object.Equals(originalValue, confirmValue);
bool foundWithValue = false;
foreach (PropertyDescriptor prop in properties) {
if (MustHaveAtLeastOneOfProperties.Contains(prop.Name)) {
object val = prop.GetValue(value);
if (val != null && val.GetType().Name.ToLower().EndsWith("string")) {
if (string.IsNullOrWhiteSpace((string)val)) {
val = null;
}
}
if (val != null) {
foundWithValue = true;
}
}
}
return foundWithValue;
}
}

C#, Generics, Reflection, Silverlight, Web Development

Map query string parameters to properties of an object, easily`

So, how many people have done this?


URL: http://.../something.aspx?PersonID=4&ChildID=16

void () {
// Assuming o = some object with properties PersonID and ChildID
PersonWithChild o = new PersonWithChild();
string _personID = Request.QueryString["PersonID"];
if (int.TryParse(_personID, out personID) {
o.PersonID = personID;
}
string _childID = Request.QueryString["ChildID"];
if (int.TryParse(_childID, out childID) {
o.ChildID = childID;
}
...
}

What a pain! This kind of plumbing is unnecessary, although frameworks like MVC have this taken care of.
Silverlight uses the concept of querystrings to pass data between pages of a navigation business application, so the code below can be used with Silverlight in addition to whatever .Net-based web framework of your choosing.

(I know code is cut off, copy and paste it and it will be fine)

Non-SL:

void init() { // This is where you initialization code may be
PersonWithChild o = new PersonWithChild();
MapQueryString(Request.QueryString, ref o, false);
// Properties are now set
}

Silverlight:

void init() { // This is where you initialization code may be
PersonWithChild o = new PersonWithChild();
// Silverlight querystring object is an IDictionary so use extension method ToQueryString()
MapQueryString(NavigationContext.QueryString.ToQueryString(), ref o, false);
// Properties are now set
}

Here are the functions: Put them into a static class in your project.

///

/// Transforms a dictionary of key/value pairs strongly typed as strings
/// into a querystring that can be parsed by MapQueryString of T.
///

///
///
public static string ToQueryString(this IDictionary kvps) {
string query = "";
foreach (var key in kvps) {
query += string.Format("{0}={1}&", key.Key, key.Value);
}
return query.TrimEnd('&');
}

///

Takes a query string and maps each key value pair to public properties of an object of type TEntity.
///

/// The class of the type of object.
/// A string containing key/value pairs.
/// The object whose properties will be populated.
/// If true, the property names and keys from the key-value pairs must match exactly.
/// An array of strings that separates each key-value pair. Passing null will default the list to {&, &}.
/// The string that separates each key and value in a key-value pair. By default this is "=".
/// If multiple parameters with the same key are specified, they are concatenated with this string, by default ",".
///
/// Since a query string can have multiple keys with the same name, a Dictionary generic was not used.
///
public static void MapQueryString(string queryString, ref TEntity o, bool caseSensitive = false, string[] separatorStrings = null, string keyValueSeparator = "=", string multipleValueJoinSeparator = ",") {
if (separatorStrings == null) { separatorStrings = new string[] { "&", "&" }; }
List kvps = GetKeyValuePairs(queryString, separatorStrings, keyValueSeparator);
Type type = o.GetType();
var properties = type.GetProperties(BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
foreach (var property in properties) {
List kv;
// Get all matching values
if (caseSensitive) {
kv = kvps.Where(p => p.Key == property.Name).ToList();
} else {
kv = kvps.Where(p => p.Key.ToLower() == property.Name.ToLower()).ToList();
}
if (kv.Count > 0) {
// Concatenate the values
string value = "";
foreach (var kvp in kv) {
if (value.Length > 0) { value += multipleValueJoinSeparator; }
value += kvp.Value;
}
object target = null;
Type ptype = property.PropertyType;
if (ptype.FullName.Contains("Nullable")) {
ptype = ptype.GetProperty("Value").PropertyType;
}
if (ptype != typeof(string)) {
try {
target = ptype.InvokeMember("Parse", BindingFlags.InvokeMethod, null, target, new object[] { value });
property.SetValue(o, target, null);
} catch (Exception ex) { }
} else {
property.SetValue(o, value, null);
}
}
}
//return o;
}

///

Turns a query string into a map of key-value pairs.
///

///
///
///
///
public static List GetKeyValuePairs(string queryString, string[] separatorStrings, string keyValueSeparator) {
List output = new List();
string[] kvps = queryString.Split(separatorStrings, StringSplitOptions.RemoveEmptyEntries);
foreach (string kvp in kvps) {
string[] t = kvp.Split(new string[] { keyValueSeparator }, StringSplitOptions.RemoveEmptyEntries);
NonUniqueKeyValuePairStruct op = new NonUniqueKeyValuePairStruct();
if (t.Length == 1) {
op.Key = null;
op.Value = t[0];
} else {
op.Key = t[0];
op.Value = t[1];
}
output.Add(op);
}
return output;
}

///

Used to hold non-unique key-value pairs.
///

public struct NonUniqueKeyValuePairStruct
{
public string Key;
public string Value;
}

C#, EF Entity Framework, Generics, RIA Services, Silverlight

Executing RIA Service Calls One-At-A-Time

Without going into details (because I’m not allowed to), I’m working on a RIA services app where one page has a large data-bound collection of buttons. Each button toggles a state, on or off. When the button is clicked, a RIA service call is performed to modify the state of the bound data, which sets the button state to Busy, setting a BusyIndicator to busy. When the callback returns, the busy state is turned off, and the details on the button are updated to reflect the change in data that I requested. While the button is “busy”, you’re not able to click it again until the callback is executed, which then re-enables the button. This list of buttons is in a wrap panel, and in my scenario, it represents a list of 1000+ objects whose state can be toggled on or off.

Everything was working very well, except if you clicked more than one button without waiting for the previous button’s callback to execute. On my local network, the callback time is very small (well under one second), but I could easily click a bunch of buttons really quickly, which would in turn cause RIA services to try to execute more than one call to update data at a time, which is not allowed.

InvalidOperationException: A SubmitChanges operation is already in progress on this DomainContext.

That throws a wrench in my gears! My options were:

  1. Add a BusyIndicator to the wrap panel, and setting it to be busy after each click;
  2. Try to get the calls to execute one-at-a-time by queuing them.

The first option was considered, but the problem there is that no other button could be toggled while the RIA service was running. Speed in clicking buttons in this list is key, and having the whole wrap panel be busy and not busy would make it flash a lot, and it’s just not as clean as having the RIA service calls execute in a queue.

My ExecuteOneAtATimeQueue class takes care of queuing RIA service calls, or any other asynchronous calls that can only run one-at-a-time such as WebClient.

Class code:

 

using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;

namespace Derreck Dean
{


 // item being modified
 // item in queue
 // function to execute

 // 1. Object is added to the queue...
 //    a. Item (userstate) being modified
 //    b. Function defining how to load image

 internal class ExecuteOneAtATimeQueue : IDisposable, INotifyPropertyChanged
 {
 public ObservableCollection<ExecuteOneAtATimeQueueItem> Queue = null;

 public event EventHandler QueueItemWorkStarted;
 public event EventHandler QueueItemWorkCompleted;
 public event EventHandler AllQueueItemsCompleted;

 private NotifyCollectionChangedEventHandler ncceh;
 private bool canProcessQueue = false;

 public ExecuteOneAtATimeQueueItem CurrentItem {
 get {
 return _currentItem;
 }
 internal set {
 _currentItem = value;
 OnPropertyChanged("CurrentItem");
 }
 }
 private ExecuteOneAtATimeQueueItem _currentItem;

 /// <summary>
 /// Init
 /// </summary>
 public ExecuteOneAtATimeQueue() {
 ncceh = new System.Collections.Specialized
 .NotifyCollectionChangedEventHandler(Queue_CollectionChanged);
 Queue = new ObservableCollection<ExecuteOneAtATimeQueueItem>();
 Queue.CollectionChanged += ncceh;
 }

 public void BeginProcessingQueue() {
 canProcessQueue = true;
 if (Queue.Count > 0)
 processQueue();
 }

 /// <summary>
 /// Adds an item to the queue.
 /// </summary>
 /// <param name="queueItem"></param>
 public void Add(ExecuteOneAtATimeQueueItem queueItem) {
 queueItem.WorkStarted += new EventHandler(queueItem_WorkStarted);
 queueItem.WorkCompleted += new EventHandler(queueItem_WorkCompleted);
 queueItem.PropertyChanged += 
 new PropertyChangedEventHandler(queueItem_PropertyChanged);
 lock (Queue) {
 Queue.Add(queueItem);
 }
 }

 /// <summary>
 /// Called when the item in the collectiom changes
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 void queueItem_PropertyChanged(object sender, PropertyChangedEventArgs e) {
 processQueue();
 }

 /// <summary>
 /// Adds work to the queue.
 /// </summary>
 /// <param name="itemToModify">Item being modified and returned.</param>
 /// <param name="userState">Optional extra data to be passed in; can be null.</param>
 /// <param name="method">Void function taking in queue item, 
 /// itemToModify and userState.</param>
 public void Add(object itemToModify, object userState, 
 Action<ExecuteOneAtATimeQueueItem, object, object> method) 
 {
 ExecuteOneAtATimeQueueItem qi = new ExecuteOneAtATimeQueueItem(itemToModify, userState);
 qi.DoWork = method;
 Add(qi);
 }

 internal void queueItem_WorkCompleted(object sender, EventArgs e) {
 if (QueueItemWorkCompleted != null) { QueueItemWorkCompleted(sender, e); }
 //processQueue(); // Continue processing queue
 }

 internal void queueItem_WorkStarted(object sender, EventArgs e) {
 if (QueueItemWorkStarted != null) { QueueItemWorkStarted(sender, e); }
 }

 /// <summary>
 /// Process the contents of the queue, if we are able.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void Queue_CollectionChanged(object sender, 
 System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
 {
 processQueue();
 }

 /// <summary>
 /// Processes the queue if we're allowed, and starts work if we are able to.
 /// </summary>
 internal void processQueue() {
 if (canProcessQueue) {
 // See if there are any busy items in the queue. 
 // If there is not, then pop one off the stack and start executing it.
 // If there are no more items in the queue, we're finished.
 bool areAnyBusy = Queue.Any(qq => qq.IsBusy == true && qq.IsCompleted == false);
 var workToDo = Queue
 .Where(qq => qq.IsBusy == false && qq.IsCompleted == false).ToList();
 if (!areAnyBusy && workToDo.Count > 0) {
 var q = workToDo.First();
 q.StartWork();
 // Done in Item object: if (QueueItemWorkStarted != null) { 
 QueueItemWorkStarted(q, null); 
 }
 } else {
 // See if everything has been completed
 if (Queue.All(qq => qq.IsCompleted == true)) {
 if (AllQueueItemsCompleted != null) { 
 AllQueueItemsCompleted(this, new EventArgs()); 
 }
 }
 }
 }
 }

 /// <summary>
 /// Queue item for work to complete.
 /// </summary>
 internal class ExecuteOneAtATimeQueueItem : INotifyPropertyChanged
 {

 /// <summary>
 /// Time work was started.
 /// </summary>
 public DateTime? StartedWork {
 get { return _startedWork; }
 internal set {
 _startedWork = value;
 OnPropertyChanged("StartedWork");
 OnPropertyChanged("IsBusy");
 OnPropertyChanged("IsCompleted");
 }
 }
 private DateTime? _startedWork = null;

 /// <summary>
 /// Time work was completed, with or without errors.
 /// </summary>
 public DateTime? EndedWork {
 get { return _endedWork; }
 internal set {
 _endedWork = value;
 OnPropertyChanged("EndedWork");
 OnPropertyChanged("IsBusy");
 OnPropertyChanged("IsCompleted");
 }
 }
 private DateTime? _endedWork = null;

 /// <summary>
 /// The item that is being worked on
 /// </summary>
 public object ItemToModify { get; set; }

 /// <summary>
 /// Another object passed to DoWork that can be modified/used
 /// </summary>
 public object UserState { get; set; }

 /// <summary>
 /// Describes if the current item is busy or not.
 /// We know this if startedWork is null or if endedWork is not null.
 /// </summary>
 public bool IsBusy {
 // IsBusy: Work has started but not completed
 get { return (_startedWork != null && _endedWork == null); }
 }

 /// <summary>
 /// Returns true if the work for this queue item has been completed.
 /// </summary>
 public bool IsCompleted {
 get { return (_startedWork != null && _endedWork != null); }
 }

 // Describes if there was a problem running the function or not.
 public bool IsError {
 get { return _isError; }
 set { _isError = value; OnPropertyChanged("IsError"); }
 }
 private bool _isError = false;

 ////////////////////////////////////////////////////////////////////////////////////////

 internal bool _hasWorkCompletedEventBeenRaised = false;

 internal event EventHandler WorkCompleted;
 internal event EventHandler WorkStarted;

 ////////////////////////////////////////////////////////////////////////////////////////

 public ExecuteOneAtATimeQueueItem() { }
 public ExecuteOneAtATimeQueueItem(object itemToModify) {
 this.ItemToModify = itemToModify;
 }
 public ExecuteOneAtATimeQueueItem(object itemToModify, object userState) {
 this.ItemToModify = itemToModify;
 this.UserState = userState;
 }

 /// <summary>
 /// Function that is called to begin work on an item.
 /// The ExecuteOneAtATimeQueueItem.EndWork() method must be called at the 
 /// end to mark the queue item as completed.
 /// The first object is the object being modified.
 /// The second object is extra stuff that can be passed in to aid in the work being run.
 /// </summary>
 public Action<ExecuteOneAtATimeQueueItem, object, object> DoWork { get; set; }

 /// <summary>
 /// Called when work ends and the queue item can be marked as done.
 /// </summary>
 /// <param name="isError"></param>
 /// <param name="userState"></param>
 public void EndWork(bool isError, object userState) {
 EndedWork = DateTime.Now;
 this.IsError = isError;
 if (!_hasWorkCompletedEventBeenRaised) {
 if (WorkCompleted != null) { WorkCompleted(this, new EventArgs()); }
 _hasWorkCompletedEventBeenRaised = true;
 }
 }

 /// <summary>
 /// Called when work is started.
 /// </summary>
 public void StartWork() {
 if (this.IsBusy)
 throw new InvalidOperationException("Work has already started for this item.");
 StartedWork = DateTime.Now;
 if (WorkStarted != null) { WorkStarted(this, new EventArgs()); }
 if (DoWork != null) { DoWork(this, ItemToModify, UserState); }
 }

 #region INotifyPropertyChanged Members

 public event PropertyChangedEventHandler  PropertyChanged;

 internal void OnPropertyChanged(string s) {
 if (PropertyChanged != null) {
 PropertyChanged(this, new PropertyChangedEventArgs(s));
 }
 }

 #endregion
 }


 #region IDisposable Members

 public void Dispose() {
 Queue.CollectionChanged -= ncceh;
 Queue = null;
 }

 #endregion

 #region INotifyPropertyChanged Members

 public event PropertyChangedEventHandler  PropertyChanged;

 private void OnPropertyChanged(string s) {
 if (PropertyChanged != null) {
 PropertyChanged(this, new PropertyChangedEventArgs(s));
 }
 }

 #endregion
 }

}

Using The Class

Using the class is pretty easy. First, create a queue object in your viewmodel or control:

 

 private ExecuteOneAtATimeQueue queue;

Initialize the queue when you’re ready to use it:

 

 queue = new ExecuteOneAtATimeQueue();
 queue.BeginProcessingQueue();

BeginProcessingQueue() instructs the queue to start processing whatever items it already has or receives immediately. You can pre-populate the queue and then call BeginProcessingQueue(), or do what I did and just start adding items whenever you like.

So here’s my offending code, which failed when the buttons were clicked too fast:

void setObjectState(...) {
 ...
 Reference.ObjectData.SubmitChanges(so => { // BOOM
 if (callback != null) {
 if (so.HasError) {
 so.MarkErrorAsHandled();
 }
 callback(userState, so.Error);
 }
 }, true);
 ...
 }

 

Here’s the change to that call that was made, to queue it up and execute it.

 

 void setObjectState(...) {
 ...
 queue.Add(null, null, (qi, item, us) => {
 Reference.ObjectData.SubmitChanges(so => {
 if (callback != null) {
 if (so.HasError) {
 so.MarkErrorAsHandled();
 }
 callback(userState, so.Error);
 }
 qi.EndWork(so.HasError, null);
 }, true);
 });
 ...

}

I didn’t need to pass in any objects to modify during the callback, so I set both to null. In the queue.Add(…) statement, “qi” refers to the internal class instance ExecuteOneAtATimeQueueItem, which you must call EndWork() to tell the queue to move onto the next QueueItem instance and begin work. “item” and “us” (for user state) are both null, since nulls were passed in as the first two parameters to the Add() method. You can pass in two objects to work with if you need, I didn’t need them here though.

With this class, I added five lines of code to queue up RIA service calls, although your mileage may vary. Now I’m not disabling the whole wrap panel, I’m only setting each button instance to busy/disabled until the callback is called.

C#, DB Database Conversion, EF Entity Framework, Generics, Serialization

Database Conversion Script Helper Functions

Sorry it’s been so long since my last post, life has kept me quite busy!

I’m writing a database conversion script for work. I modified an older version of a database for a project and made numerous changes to the schema. Transferring data from the old database to the new database after such changes have been made is not an easy task: renamed columns are trivial, but foreign-key lookup tables are not. Making matters worse is that I can never get the SSMS Copy Database Wizard to work correctly, and when I just use the Script Database with Data option, figuring I could use some regular expressions to convert the generated script to be used with the new schema, SSMS gives me ‘Out of memory’ exceptions. Therefore, I decided to make a database conversion console program that I can run a few times, since it’s not a one-time conversion – I need to test the conversion, then have a basic version of the program for the owner of the company I work for and the end-user to test with, and then the final copy of the data to be transferred to the new database when the end-user starts working with the new software.

I came up with some helper functions I made to ease the creation of the script. Some of the tables from the old database remained unchanged in the new database, which I used _directCopy() to copy the data; for tables with changes, I used _kindaDirectCopy() to make the changes. This was done in a console program, so the static prefixes can be removed depending on your use.

/// <summary>
/// Log to screen and debug
/// </summary>
/// <param name="s"></param>
static void log(string s) {
 string op = string.Format("{0}: {1}", DateTime.Now.ToString().PadLeft(25, ' '), s);
 Console.WriteLine(op);
 Debug.WriteLine("*** " + op);
}

/// <summary> Clones an object to a similar type. The TResult and TSource must have the same properties,
/// but can be from two different namespaces.
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
static TResult cloneObjectToAnotherGraph<TSource, TResult>(TSource source) {
 MemoryStream ms = new MemoryStream();
 //BinaryFormatter bf = new BinaryFormatter();
 XmlSerializer xs = new XmlSerializer(typeof(TSource));
 //bf.Serialize(ms, source);
 xs.Serialize(ms, source);
 ms.Position = 0;
 // This part takes anything in the serialized portion that is referencing
 // "OldDB" and converting it to "NewDB" so EF doesn't gripe when I try to 
 // add the serialized object back into the new database.
 byte[] buffer = stringToBuffer(bufferToString(ms.ToArray()).Replace("OldDB", "NewDB"));
 ms.Close();
 xs = new XmlSerializer(typeof(TResult));
 //object obj = bf.Deserialize(ms);
 object obj = xs.Deserialize(new MemoryStream(buffer)); // xs.Deserialize(ms);
 ms.Close();
 TResult t = (TResult)obj;
 // Detach the entity from the old DB and attach to the new entity by creating a new entity key.
 string tn = (typeof(TResult)).ToString();
 tn = tn.Substring(tn.LastIndexOf('.') + 1);
 string key = "NewDBEntities." + tn;
 (t as EntityObject).EntityKey = newDB.CreateEntityKey(key, t);
 return t;
}

/// <summary> Converts a byte array into a string.
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
static string bufferToString(byte[] buffer) {
 /*
 StringBuilder sb = new StringBuilder();
 foreach (byte b in buffer) {
 sb.Append(b.ToString());
 }
 return sb.ToString();
 */ 
 return System.Text.Encoding.UTF8.GetString(buffer);
}

/// <summary> Converts a string into a byte array.
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
static byte[] stringToBuffer(string s) {
 return System.Text.Encoding.UTF8.GetBytes(s);
}

/// <summary>  Gets the name of the underlying database table.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
static string getTableNameFromEntityList<T>(ObjectSet<T> source) where T : class {
 var p = source.EntitySet.ElementType.MetadataProperties.SingleOrDefault(e => e.Name == "Name");
 if (p != null) { return (string)p.Value; } else { return null; }
}

/// <summary> Turns identity insert ON or OFF for a given table in a given data context.
/// </summary>
/// <param name="store"></param>
/// <param name="tableName"></param>
/// <param name="onOff"></param>
static void setTableIdentityInsert(ObjectContext store, string tableName, bool onOff) {
 if (string.IsNullOrWhiteSpace(tableName)) { return; } // Do nothing if the table name is null or empty.
 try {
 store.ExecuteStoreCommand(string.Format("SET IDENTITY_INSERT {0} {1};",
 tableName,
 onOff ? "ON" : "OFF"));
 } catch (SqlException) {
 // Do nothing, it means that the table has no identity column
 } catch (Exception) {
 throw;
 }
}

/// <summary> Performs a direct translation of items in a source list of a type TSource into a
/// destination list of type TResult by serializing each source object and restoring it
/// into a TResult object. TSource and TResult must be the same object structure, or at
/// least able to serialize the contents of TSource and deserialize into TResult.
/// Used for database conversion scripts, where identical entities cannot be interchanged
/// normally because the types still differ (even if it is only the namespace that differs).
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="sourceList"></param>
/// <param name="destList"></param>
static void _directCopy<TSource, TResult>(ObjectSet<TSource> sourceList, ObjectSet<TResult> destList) 
 where TSource : class
 where TResult : class
{
 // Get the name of the underlying table, to turn on identity insert
 setTableIdentityInsert(newDB, getTableNameFromEntityList<TResult>(destList), true);
 long count = 0;
 sourceList.ToList().ForEach(x => {
 var y = cloneObjectToAnotherGraph<TSource, TResult>(x);
 destList.AddObject(y);
 count++;
 });
 newDB.SaveChanges(); // this can be taken out, it's just in for persistence.
 // Turns off identity insert.
 setTableIdentityInsert(newDB, getTableNameFromEntityList<TResult>(destList), false);
 log(string.Format("{0}: {1}",
 count.ToString().PadLeft(10, ' '),
 typeof(TResult).Name));
}

/// <summary> Performs a translation of items in a source list of a type TSource into a destination
/// list of type TResult by invoking a delegate/anonymous function that performs the conversion
/// of each object from TSource to a TResult.
/// If identityInsertTableName is not null, then identity insert is turned ON for the duration of
/// the call, and turned off before completing. Leave this as null if you don't want identity insert on.
/// Used for database conversion scripts where the two objects differ.
/// The counter is passed into the delegate, to be used in situations where you need an auto-incrementing
/// ID (example: When a surrogate autonumbering key is added to a table with no key/natural keys).
/// </summary>
static void _kindaDirectCopy<TSource, TResult>(ObjectSet<TSource> sourceList, ObjectSet<TResult> destList, Func<TSource, int, TResult> conversionDelegate)
 where TSource : class
 where TResult : class 
{
 setTableIdentityInsert(newDB, getTableNameFromEntityList<TResult>(destList), true);
 int counter = 0;
 sourceList.ToList().ForEach(x => {
 TResult y = conversionDelegate.Invoke(x, ++counter);
 destList.AddObject(y);
 });
 newDB.SaveChanges();
 setTableIdentityInsert(newDB, getTableNameFromEntityList<TResult>(destList), false);
}

Here’s how to use the code:

// aspnet_Applications
_directCopy<OldDB.aspnet_Applications, NewDB.aspnet_Applications>(oldDB.aspnet_Applications, newDB.aspnet_Applications);

// aspnet_SchemaVersions
_directCopy<OldDB.aspnet_SchemaVersions, NewDB.aspnet_SchemaVersions>(oldDB.aspnet_SchemaVersions, newDB.aspnet_SchemaVersions);

// aspnet_Users
_directCopy<OldDB.aspnet_Users, NewDB.aspnet_Users>(oldDB.aspnet_Users, newDB.aspnet_Users);

// aspnet_WebEvent_Events
_directCopy<OldDB.aspnet_WebEvent_Events, NewDB.aspnet_WebEvent_Events>(oldDB.aspnet_WebEvent_Events, newDB.aspnet_WebEvent_Events);
 
// aspnet_Paths
_directCopy<OldDB.aspnet_Paths, NewDB.aspnet_Paths>(oldDB.aspnet_Paths, newDB.aspnet_Paths);
 
// aspnet_Roles
_directCopy<OldDB.aspnet_Roles, NewDB.aspnet_Roles>(oldDB.aspnet_Roles, newDB.aspnet_Roles);


// Notes
_directCopy<OldDB.Note, NewDB.Note>(oldDB.Notes, newDB.Notes);

// Contact Types
_directCopy<OldDB.ContactType, NewDB.ContactType>(oldDB.ContactTypes, newDB.ContactTypes);

// Contacts - The old table had a natural key and the new table has a surrogate auto-incrementing
//        key, so I used the count parameter to give me an incrementing number to use
_kindaDirectCopy<OldDB.Contact, NewDB.Contact>(oldDB.Contacts, newDB.Contacts, (x, count) => {
 return new NewDB.Contact() {
 ContactID = count,
 ContactInfo = x.ContactInfo,
 ContactTypeID = x.ContactTypeID,
 OrganizationID = _org,
 PersonID = x.PersonID
 };
});

 

Hope this helps.

Uncategorized

iTunes Lyrics Finder + Invalid File Remover

If you use iTunes, this handly little program will find lyrics from http://lyric.wikia.org for your songs. On the iPhone, you can tap the background and read the lyrics while playing songs in the iPod app.

derreckdean.com-iTunesLyricsFinder.zip (189kb)

This is an update from my older post, but since the Lyrics Wiki removed the lyrics API, this program hasn’t worked in some time. However, I now just scrape whats on the web page at the lyrics wiki. Therefore, you should know that the process is a little slow, so be patient.

Also, this won’t modify any songs with existing lyrics. If the lyrics don’t exist for that song, then ILF will download them.