Trouble binding entity framework 5 object with windows control - winforms

I'm using Entity Framework for the first time (database first, entity framework 5) in a windows forms application (vs2010, .net 4). I am having trouble with the binding between my entity object and the windows forms controls. I have textbox, datetimepicker and combobox controls. When I open a window with the bound controls, the correct data is displayed in the controls. However, when I change the value in one of my controls and tab off the control, the value reverts to the original value in the control as if the value is not getting pushed to the object. Here are code exerpts:
My entity object:
namespace Entities
{
using System;
using System.Collections.Generic;
public partial class ExternalDocument
{
public int ExternalDocumentID { get; set; }
public bool Active { get; set; }
public bool Closed { get; set; }
public Nullable<int> CompanyID { get; set; }
public Nullable<int> ContactID { get; set; }
public string DocumentNbr { get; set; }
public Nullable<System.DateTime> DocumentDate { get; set; }
public Nullable<System.DateTime> DateReceived { get; set; }
public virtual Company Company { get; set; }
public virtual Contact Contact { get; set; }
}
}
The data binding:
private void SetDataBindings()
{
LoadComboBoxValues();
this.textDocumentNbr.DataBindings.Add("Text", this.document, "DocumentNbr");
this.textDocumentNbr.Leave += new EventHandler(textDocumentNbr_Leave);
this.dateDocument.DataBindings.Add(new Binding("Value", this.document, "DocumentDate"));
this.dateReceived.DataBindings.Add("Value", this.document, "DateReceived");
this.comboCompanyID.DataBindings.Add("SelectedValue", document, "CompanyID");
}
I have wondered if there is an entity framework error when the object property is set but I have not been able to figure out a good way to trap any such errors. My entity framework object does not have the On< PropertyName >Changing methods that are created for earlier versions of entity framework. I have been trying to trap errors when focus leaves the control but think this can't be the best method:
private void dateDocument_Leave(object sender, EventArgs e)
{
string errorString = this.entitiesController.GetValidationErrors();
this.errorDocumentDate.SetError(this.dateDocument, errorString);
}
public string GetValidationErrors()
{
string errorString = "";
List<DbEntityValidationResult> errorList = (List<DbEntityValidationResult>)this.finesse2Context.GetValidationErrors();
if (errorList.Count > 0)
{
foreach(var eve in errorList)
{
errorString += "Entity of type " + eve.Entry.Entity.GetType().Name + " in state" + eve.Entry.State + " has the following validation errors:"; ;
foreach (var ve in eve.ValidationErrors)
{
errorString += "- Property: " + ve.PropertyName + " Error: " + ve.ErrorMessage;
}
}
}
return errorString;
}
Any help would be appreciated. Thanks!

It turns out that an exception is received when the binding pushes a non nullable value to a nullable property in the object unless "formattingEnabled" is specified on the binding.
So, binding like this works:
this.dateDocument.DataBindings.Add(new Binding("Value", this.document, "DocumentDate", true));
whereas this does not:
this.dateDocument.DataBindings.Add(new Binding("Value", this.document, "DocumentDate"));
I am still unclear how I could trap that type of error since the Binding simply catches the error and replaces the value in the control with the original value.

Related

Protobuf-Net Silverlight: DataContract class has properties null or missing

This is one of the class definitions within a DLL I use in my WCF service.
[DataContract]
public class ScenarioXML
{
[DataMember(Order = 1)]
public long? TNRScenario { get; set; }
[DataMember(Order = 2)]
public long? TNRProject { get; set; }
[DataMember(Order = 3)]
public int? Priority { get; set; }
// ...
[DataMember(Order = 19)]
public List<ScenarioAssetXML> ScenarioAssets { get; set; }
[DataMember(Order = 20)]
public List<CalendarXML> Calendars { get; set; }
[DataMember(Order = 21)]
public ScenarioTriggerCollectionXML ScenarioTriggerCollection { get; set; }
}
I'm using DataContract instead of ProtoContract, so I can expose this class to a Silverlight project through a WSDL, and still use Protobuf-net for serialization.
Now, when I use the following code in my WCF service, the original "scenario" and the "restoredModel" are identical.
MemoryStream msTestString = new MemoryStream();
Serializer.Serialize<ScenarioXML>(msTestString, scenario);
string memento = Convert.ToBase64String(msTestString.ToArray());
byte[] byteAfter64 = Convert.FromBase64String(memento);
MemoryStream afterStream = new MemoryStream(byteAfter64);
ScenarioXML restoredModel = Serializer.Deserialize<ScenarioXML>(afterStream);
However, when I use the same code in Silverlight, the TNRScenario value is null.
Similarly, the TNRScenarioAsset property of the objects in the ScenarioAssets list are null.
[DataContract]
public class ScenarioAssetXML
{
[DataMember(Order = 1)]
public long? TNRScenarioAsset { get; set; }
[DataMember(Order = 2)]
public long? TNRScenario { get; set; }
[DataMember(Order = 3)]
public string Asset { get; set; }
[DataMember(Order = 4)]
public string Action { get; set; }
}
When I make the first property a string, it completely vanishes after (de)serialization. When I put a dummy bool as a first property, the bool is there, but the second property, in this case ScenarioAssets, is still null. There's something weird going on here...
Am I doing somethign wrong, or is this a bug?
Edit:
You're right Marc! The orders get messed up in the WSDL-generated code.
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="ScenarioXML", Namespace="http://schemas.datacontract.org/2004/07/DataCollectionDLL")]
public partial class ScenarioXML : object, System.ComponentModel.INotifyPropertyChanged {
private System.Nullable<long> TNRScenarioField;
private System.Nullable<long> TNRProjectField;
private System.Nullable<int> PriorityField;
//...
[System.Runtime.Serialization.DataMemberAttribute()]
public System.Nullable<long> TNRScenario {
get {
return this.TNRScenarioField;
}
set {
if ((this.TNRScenarioField.Equals(value) != true)) {
this.TNRScenarioField = value;
this.RaisePropertyChanged("TNRScenario");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(Order=1)]
public System.Nullable<long> TNRProject {
get {
return this.TNRProjectField;
}
set {
if ((this.TNRProjectField.Equals(value) != true)) {
this.TNRProjectField = value;
this.RaisePropertyChanged("TNRProject");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(Order=2)]
public System.Nullable<int> Priority {
get {
return this.PriorityField;
}
set {
if ((this.PriorityField.Equals(value) != true)) {
this.PriorityField = value;
this.RaisePropertyChanged("Priority");
}
}
}
//...
However, I'm not sure how to correctly implement that partial class? I created it in the WCF service, but that seems to confuse the compiler. Getting the following errors:
Error 6 'DataCollectionDLL.ScenarioXML' does not contain a definition for 'TNRScenario' and no extension method 'TNRScenario' accepting a first argument of type 'DataCollectionDLL.ScenarioXML' could be found (are you missing a using directive or an assembly reference?)
Error 2 Cannot convert type 'DataCollectionDLL.ScenarioXML [c:\Projects\Flowcontrol 1.7.1.1\flowcontrolFC.Web\Libraries\DataCollectionDLL.dll]' to 'DataCollectionDLL.ScenarioXML [C:\Projects\Flowcontrol 1.7.1.1\flowcontrolFC.Web\DAL\DataCollectionClasses\ScenarioXML.cs(31)]'
Then tried it in the Silverlight project, which compiles fine but that doesn't solve the problem. Results are the same.
The partial class I created:
namespace DataCollectionDLL
{
[ProtoContract]
[ProtoPartialMember(1, "TNRScenario")]
[ProtoPartialMember(2, "TNRProject")]
[ProtoPartialMember(3, "Priority")]
//...
[ProtoPartialMember(21, "ScenarioTriggerCollection")]
partial class ScenarioXML
{
}
}
It sounds like you used WSDL-generated proxies; that can confuse things a little bit, because protobuf-net really really cares what the numbers are, and WSDL can sometimes play fast and loose with those. It would really help if I could see the WSDL-generated proxy classes (in the .designer.cs), but I'm going to assume this is the problem. Fortunately, most code-generators use partial class, so you can add your own partial class in a separate file to add extra information into the same type, in particular: more attributes. For example:
namespace The.Same.Namespace
{
[ProtoContract]
[ProtoPartialMember(1, "TNRScenario")]
[ProtoPartialMember(2, "TNRProject")]
// ...
[ProtoPartialMember(21, "ScenarioTriggerCollection")]
partial class ScenarioXML { }
}
This will get merged by the compiler into the ScenarioXML class, and should allow protobuf-net to use the correct numeric identifiers for each property.

WPF MVVM View with lookup or join to other entities

I am getting started with WPF and MVVM. I am just reading up on Code Project Article which is quite interesting and provides a good quick start. I am using Entity Framework and I am happy I have listed all of my entities in a ListView.
I am curious how you would correctly implement lookups - in the view model or create a new model. Take the simple case of a person. The data structure might be:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public Toy FaveToy { get; set; }
}
public class Toy
{
public string Name { get; set; }
public string Model { get; set; }
public string Manufacturer { get; set; }
}
I want my list view to show the columns FirstName, LastName, DateOfBirth, Fave Toy, Manufacturer.
The Toy field will be a combined string with Name + " " + Model in.
So given some of the code in the example I've linked (I've knocked the Person class up for examples sake):
Base Class for the views
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
My implementation for the Person view
public class PersonViewModel : ViewModelBase
{
private ObservableCollection<Person> _Person;
public PersonViewModel()
{
_Person = new ObservableCollection<Person>();
Entities context = new Entities();
foreach(var person in context.Person.ToList())
{
_Person.Add(person);
}
}
public ObservableCollection<Person> Person
{
get
{
return _Person;
}
set
{
_Person = value;
this.OnPropertyChanged("Person");
}
}
}
If I am understanding correct you want to access a Toy through the FaveToy property automatically.
Normally this would be done creating a relation between Person and Toy. Once you've done so your Person entity type would look like this:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public virtual Toy FaveToy { get; set; }
}
Notice the "virtual" on FaveToy. This indicates a navigation property which would be accessible through person instance.FaveToy. This can be represented in XAML either through dot notation or using the path property on your binding. Here is a link that discusses navigation properties: http://msdn.microsoft.com/en-us/data/jj713564.aspx
If you want to represent the toy by a combination of name and model then a converter would do the trick on the binding. Here is a link that discusses converters http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx
Hope this helps...Jason
PS - Josh Smith is awesome in his discussion of WPF and MVVM http://joshsmithonwpf.wordpress.com/a-guided-tour-of-wpf/
If you're a VB guy Alessandro has trhe best discussion for VB that I've seen: http://community.visual-basic.it/Alessandroenglish/archive/2010/08/13/31861.aspx
PSS -- WPF and MVVM (or Windows 8 and XAML) are awesome. Definitely worth your time to pick up.

Which one is a better data design or object model?

Overview
I am designing a mechanism for generating dynamic controls in an ASP.NET MVC application that uses ADO.NET Entity Framework. However, my question has nothing to do with MVC and a little to do with the Entity Framework. It is about comparing two object models.
Problem Statement
In my app, a user must have the ability to interact with Web page A to specify that he wants to add such and such HTML controls to Web Page B.
When he browses Web Page B next, he must see those controls and be able to use them.
What Is Not The Challenge
I have written the code to generate the controls. That was the easy part. I used the Tag Builder, Partial Views, HtmlHelper extensions and Display & Editor templates.
The Challenge
The challenge is in arriving at a database design and an object model generated by Entity Framework to hold the metadata about the controls that need to be generated.
I have come up with a database design as shown below:
You may ignore the User and Permissions tables. They are not relevant to our discussion.
Entity Framework generates the following entities based on the above database design.
Let's call my database design as Design Option A.
I would have wanted a design that looked more like this:
Let's call this second design as Design Option B.
The code (stripped down version) for this second option would look like this:
namespace DynamicControls
{
public class DynamicControlGroup
{
public long Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Controller { get; set; }
public IEnumerable<string> Actions { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public User CreatedByUser { get; set; }
public DateTime CreationDateTime { get; set; }
public User LastModifiedBy { get; set; }
public DateTime ModificationDateTime { get; set; }
// Navigational
public ICollection<DynamicControl<T>> DynamicControls { get; set; }
}
public class DynamicControl<T>
{
public long Id { get; set; } //db Id
public string HtmlId { get; set; }
public bool ValueRequired { get; set; }
public virtual ControlType ControlType { get; protected set; }
// Every control is capable of having a default value but of a different
// type. Most controls have default values of type text (string). The
// multi-select ones (checkboxes, multi-select lists, etc.) have a default
// value of type IEnumerable<string>. So, I want to leave this generic.
// But I am not that hung-up on this. I am fine if I am required to move
// this property DefaultValue from the base class and make it a concrete
// (not generic) property for each individual child class.
// Mostly I just want the heirarchy. And before that, I want to know
// if it is a good idea to model this heirarchy. Or is it better to just
// work with what my Entity Framework produced for my db?
// Should I change my db? I can because I thought-up the design for
// those tables.
public virtual T DefaultValue { get; set; }
// Navigational
public DynamicControlGroup DynamicControlGroup { get; set; }
}
public class TextBox : DynamicControl<string>
{
public override ControlType ControlType
{
get
{
return DynamicControls.ControlType.TextBox;
}
}
public string Label { get; set; }
public int MaxLength { get; set; }
}
public class PasswordControl : TextBox
{
public override ControlType ControlType
{
get
{
return DynamicControls.ControlType.Password;
}
}
}
public class TextArea : TextBox
{
public override ControlType ControlType
{
get
{
return DynamicControls.ControlType.TextArea;
}
}
public int Rows { get; set; }
}
public class DropDownList: DynamicControl<string>
{
public override ControlType ControlType
{
get
{
return ControlType.DropDownList;
}
}
// I want something like this. That I should be able to say
//
// myDropDownListObject.Options...
//
// You'll notice that given my current database design, I have
// no direct way of accessing the options of a, say, drop down list.
// To do that, I have to make a round-about Linq query.
public ICollection<DynamicControlOption> Options { get; set; }
}
public class DynamicControlOption
{
public long Id { get; set; } // db Id
public string OptionHtmlId { get; set; }
public string OptionValue { get; set; }
public string OptionText { get; set; }
// Navigational property
public DynamicControl<IEnumerable<string>> TheControlWhoseOptionIAm { get; set; }
}
public class User
{
}
public class Permission
{
}
public enum ControlType
{
TextBox,
TextArea,
Password,
RadioButton,
Checkbox,
DropDownList,
MultiSelectList,
DatePicker,
TimePicker,
DateTimePicker
}
}
My Question
1) I feel that I'd like Design Option B better. Am I feeling right?
2) I know I can work with Design Option A just as fine but it'll involve a little round-about way to do some things. For example, to get all the options for a drop down list, there's not navigational property on the DropDownList class in Design Option A. I'll have to write a round-about Linq query to do that.
3) Is it possible to have Entity Framework come close to generating Design Option B? How? What changes will I need to make to my database design to achieve that?
Now we are working on a Project like this at our company...
If I got your meaning correctly and If I were you...I implemented inherited structure as my database design like below.
Now you Classes are inheritance but your database design is not.
I have removed Id in TextBox and I have put ControlId as PK and FK in the same time. (not just FK).
in fact,ControlId is both PK for TextBox and FK from DynamicControl
and also this way for PasswordControl and TextArea
and Now ControlId in TextBox is not Identity. It gets it's ControlId from DynamicControl
I also accept Design Option B .I'm always more comfortable than using Design Option A.in my idea It's true and main structure

How to remove one or more fields from the DataForm.Validating() event in Silverlight 4?

I have a data form that is bound to an object whose properties are decorated with System.ObjectModel.DataAnnotation attributes for validaton.
The problem I am facing is that some properties of this class are only conditionally needed and do not need to be validated. For example when an admin of the app decides to edit a user,
he or she may enter a password/password confirm/password question/password answer. Or he/she may entirely skip those properties.
So if the admin decides to enter any of those 4 fields, they all have to be present and the validation rules for all these fields have to be applied. However if the admin only wants to change the FirstName, LastName, Email, or whatever other arbitrary properties - the password related fields do not need to be validated.
Is there a way to "Exclude" them from the validation process?
this is a sample of the object I work with:
public class RegistrationData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string PasswordConfirm { get; set; }
public string PasswordQuestion { get; set; }
public string PasswordAnswer { get; set; }
}
I have a DataForm called registrationForm in the Xaml and the error I get is in this code:
private void RegistrationButton_Click(object sender, RoutedEventArgs e)
{
if( this.registerForm.ValidateItem() )
{
//Does not pass validaton if the password properties are not filled in.
}
}
Any ideas on how to fix it?
I was thinking of using two DataForms... and split the user object in two, but that involves a lot of code...
I would recommend to use the INotifyDataError interface on your RegistrationData object.
public string LabelWrapper
{
get
{
return this.Label;
}
set
{
ValidateRequired("LabelWrapper", value, "Label required");
ValidateRegularExpression("LabelWrapper", value, #"^[\w-_ ]+$", "Characters allowed (a-z,A-Z,0-9,-,_, )");
this.Label = value;
this.RaisePropertyChanged("LabelWrapper");
}
}
public string DependentLabelWrapper
{
get
{
return this.DependentLabel;
}
set
{
if(LabelWrapper != null){
ValidateRequired("DependentLabelWrapper", value, "Label required");
ValidateRegularExpression("LabelWrapper", value, #"^[\w-_ ]+$", "Characters allowed (a-z,A-Z,0-9,-,_, )");
}
this.DependentLabel = value;
this.RaisePropertyChanged("DependentLabelWrapper");
}
}
I recommend you to look at this link http://blogs.msdn.com/b/nagasatish/archive/2009/03/22/datagrid-validation.aspx to learn more about different validation types.
Also MSDN has a nice explanation on how to use it
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifydataerrorinfo%28VS.95%29.aspx
This question brought me to another solution. I now use CustomValidation:
[CustomValidation(typeof(RegistrationDataValidation), "ValidatePassword")]
public class RegistrationData
{
public bool IsNewUser { get; set; }
... // other registration properties
}
public static class RegistrationDataValidation
{
public static ValidationResult ValidatePassword(MembershipServiceUser user, ValidationContext context)
{
if (user.IsNewUser && string.IsNullOrEmpty(user.Password))
{
return new ValidationResult("Password required");
}
return ValidationResult.Success;
}
}
I added a property IsNewUser which I set in the client when adding a new user. The custom validation method checks this property and executes the desired validation. I still have a RegularExpression Attribute on the password which will be validated as well.
In comparison to #Staindart's solution this is checked on the client synchronously.
The simplest and ugliest way would be to tap into the DataForm.ValidatingItem event. Like so:
void dfEditForm_ValidatingItem(object sender, System.ComponentModel.CancelEventArgs e)
{
foreach (ValidationSummaryItem item in dfEditForm.ValidationSummary.Errors)
{
if (item.Sources.Where(W => W.PropertyName != "myIgnoredPropertyName").Count() > 0)
e.Cancel = true;
}
}

EF 4.1 Codefirst WPF Eager Loading Data Binding

I am having problems databinding to EF code first. I need to be using Eager Loading, but I am running into some issues with databinding. I have the following classes:
public class Context : DbContext
{
DbSet<A> As;
DbSet<B> Bs;
DbSet<C> Cs;
}
public class A
{
public ICollection<B> Bs { get; set; }
public string Name { get; set; }
}
public class B
{
public ICollection<C> Cs { get; set; }
public string Name { get; set; }
}
public class C
{
public string Name { get; set; }
}
I am data binding Context.As to a Treeview, using the below code:
Context.As.Load();
tvItems.ItemsSource = Context.As.Local;
This works as expected, however, it does not automatically load the child properties, Bs, and subsequently, Cs. So, I found that lazy loading can help with this, like so:
Context.As.Load();
tvItems.ItemsSource = Context.As.Include(u=>u.Bs);
From my reading, this should automatically load at least the first level of child properties. However, this will not data bind, as I did not use .Local
.Include() returns IQueryable, which does not support .Local. I can use .ToList(), but this will not automatically update when I add items.
So, how the hell am I supposed to be doing this?
You could try this:
Context.As.Include(a => a.Bs).Load();
tvItems.ItemsSource = Context.As.Local;

Resources