remove self reference entity in EntityFramework CodeFirst - wpf

i defined bellow classes for my EF in wpf for use in mvvm pattern:
public class ProductGroup : ViewModelBase
{
public long ID { get; set; }
private string _Title;
public string Title
{
get { return _Title; }
set
{
if (_Title != value)
{
_Title = value;
this.RaisePropertyChanged("Title");
}
}
}
private byte[] _Icon;
public byte[] Icon
{
get { return _Icon; }
set
{
if (_Icon != value)
{
_Icon = value;
this.RaisePropertyChanged("Icon");
}
}
}
private ProductGroup _Parent;
public ProductGroup Parent
{
get { return _Parent; }
set
{
if (_Parent != value)
{
_Parent = value;
this.RaisePropertyChanged("Parent");
}
}
}
private ObservableCollection<ProductGroup> _Childs;
public ObservableCollection<ProductGroup> Childs
{
get { return _Childs; }
set
{
if (_Childs != value)
{
_Childs = value;
this.RaisePropertyChanged("Childs");
}
}
}
private ObservableCollection<Product> _Products;
public ObservableCollection<Product> Products
{
get { return _Products; }
set
{
if (_Products != value)
{
_Products = value;
this.RaisePropertyChanged("Products");
}
}
}
}
public class Product : ViewModelBase
{
public long ID { get; set; }
private ProductGroup _Gorup;
public ProductGroup Gorup
{
get { return _Gorup; }
set
{
if (_Gorup != value)
{
_Gorup = value;
this.RaisePropertyChanged("Gorup");
}
}
}
private string _Name;
public string Name
{
get { return _Name; }
set
{
if (_Name != value)
{
_Name = value;
this.RaisePropertyChanged("Name");
}
}
}
}
is my definitions correct ??
when i want to remove an item from ProductGroups ,The following error occurs:
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.
Note:
The target ProductGroup is a child of another ProductGroup
the target ProductGroup has no Child and Product

Related

How do I set "OnPropertyChanged" on Properties from Model?

I Have Two ComboBoxes for example Country and State where State ComboBox's ItemSource depends on Selected Country of First ComboBox.
Country and State Properties are defined in separate CountryModel(CountryID,CountryName) and StateModel(CountryID,StateID,StateName).
Now there is the Model "UserModel" is like :
public class UserModel:ViewModelBase
{
private string _userName;
public string UserName
{
get { return _userName; }
set { _userName = value; OnPropertyChanged("UserName"); }
}
private long _stateID;
public long StateID
{
get { return _stateID; }
set { _stateID = value; OnPropertyChanged("StateID"); }
}
private int _countryID;
public int CountryID
{
get { return _countryID; }
set { _countryID = value; OnPropertyChanged("CountryID"); }
}
}
It has a Service "UserModelService" for populating :
public class UserModelService
{
public UserModelService()
{
}
public ObservableCollection<UserModel> GetUserList()
{...}
public ObservableCollection<CountryModel> GetCountryList()
{...}
public ObservableCollection<StateModel> GetStateList()
{...}
}
Now The UserViewModel is Like:
public class UserViewModel:ViewModelBase,IPageViewModel
{
UserModelService modelService;
public UserViewModel()
{
modelService = new UserModelService();
GetData();
}
private void GetData()
{
UserList = modelService.GetUserList();
CountryList = modelService.GetCountryList();
StateList = modelService.GetStateList();
}
private UserModel _currentUser=new UserModel();
public UserModel CurrentUser
{
get { return _currentUser; }
set
{
if (value == _currentUser) return;
_currentUser = value; OnPropertyChanged("CurrentUser");
}
}
private ObservableCollection<UserModel> _userList;
public ObservableCollection<UserModel> UserList
{
get { return _userList; }
set
{
if (value == _userList) return;
_userList = value;
OnPropertyChanged("UserList");
}
}
private ObservableCollection<CountryModel> _countryList;
public ObservableCollection<CountryModel> CountryList
{
get { return _countryList; }
set { _countryList = value; OnPropertyChanged("CountryList"); }
}
private ObservableCollection<StateModel> _stateList;
public ObservableCollection<StateModel> StateList
{
get { return _stateList; }
set
{
_stateList = value;
OnPropertyChanged("StateList");
}
}
}
Now the Country and State ComboBox's ItemSource is binded to UserViewModels "CountryList" and "StateList" respectively. In this scenario how to I repopulate StateList OnPropertyChange of CurrentUser.CountryID?
EDIT: I Solved it by introducing separate property for Selected Country and OnPropertyChanged CurrentUser.CountryID=selectedCountry. Thanks
Handle the PropertyChanged event for the current user:
public UserModel CurrentUser
{
get { return _currentUser; }
set
{
if (value == _currentUser)
return;
if (_currentUser != null)
_currentUser.PropertyChanged -= OnCurrentUserPropertyChanged;
_currentUser = value;
if (_currentUser != null)
_currentUser.PropertyChanged += OnCurrentUserPropertyChanged;
OnPropertyChanged("CurrentUser");
}
}
private void OnCurrentUserPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(UserModel.CountryID))
{
UserModel userModel = (UserModel)sender;
var states = ...; //get states by userModel.CountryID
StateList = states;
}
}

WPF ViewModel HashCode

I have a ViewModel that has a hierarchical collection of elements:
public class TestViewModel : BindableBase
{
private ObservableCollection<TestElement> _testElementItemsSource;
private TestElement _testElementSelectedItem;
public ObservableCollection<TestElement> TestElementItemsSource
{
get { return _testElementItemsSource; }
set { this.SetProperty(ref this._testElementItemsSource, value); }
}
public TestElement TestElementSelectedItem
{
get { return _testElementSelectedItem; }
set { this.SetProperty(ref this._testElementSelectedItem, value); }
}
}
public class TestElement : BindableBase
{
private Guid _id;
private string _caption;
private ObservableCollection<TestElement> _children;
public Guid ID
{
get { return _id; }
set { this.SetProperty(ref this._id, value); }
}
public String Caption
{
get { return _caption; }
set { this.SetProperty(ref this._caption, value); }
}
public ObservableCollection<TestElement> Children
{
get { return _children; }
set { this.SetProperty(ref this._children, value); }
}
}
When changing the 'Caption' property of any 'Child' element, anywhere in hierarchy - is there a way to get some HashCode for the whole TestViewModel, to indicate that the TestViewModel become dirty/modified?

Map a Uri field using Dapper

What is the cleanest way to map a string column to a Uri property using Dapper?
Here's the cleanest I've been able to come up with so far (using the ITypeMap functionality):
Query:
SELECT * FROM TableWithAStringAddressColumn
POCO:
public class MyPoco
{
[ColumnSetter("DapperAddress")]
public Uri Address { get; set; }
private string DapperAddress { set { this.Address = new Uri(value); } }
}
Extensions:
partial class SqlMapper
{
public static void InitializeTypeMaps()
{
SqlMapper.SetTypeMap(
typeof(MyPoco),
new CustomPropertyTypeMap(typeof(MyPoco), SqlMapper.CustomSetterMapper));
// call out every other class that needs this kind of mapping
}
public static Func<Type, string, PropertyInfo> CustomSetterMapper =
(type, columnName) =>
{
PropertyInfo prop = type
.GetProperties()
.FirstOrDefault(p => string.Equals(columnName, p.Name, StringComparison.OrdinalIgnoreCase));
if (prop != null)
{
// find out if we need to use a different setter
ColumnSetterAttribute setterAttribute = prop.GetCustomAttributes(false).OfType<ColumnSetterAttribute>().LastOrDefault();
if (setterAttribute != null)
{
PropertyInfo setterProp = type
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.FirstOrDefault(p => string.Equals(setterAttribute.Setter, p.Name, StringComparison.OrdinalIgnoreCase));
if (setterProp == null)
{
throw new InvalidOperationException(string.Format("Setter property misconfigured (Property={0}, Setter={1})", prop.Name, setterAttribute.Setter));
}
else
{
prop = setterProp;
}
}
}
return prop;
};
}
Custom Attribute:
public class ColumnSetterAttribute : Attribute
{
public string Setter { get; set; }
public ColumnSetterAttribute(string setter)
{
this.Setter = setter;
}
}
[edit] I'm looking for a solution I can use without needing to call out all columns in all my queries (I'd like to find a solution where I can use SELECT *).
Seems like a lot of work...
Wouldn't this be ok?
public class MyPoco
{
private string _uriMapper;
public Uri SomeUri
{
get { return new Uri(_uriMapper); }
}
public string Mapper { set { _uriMapper = value; } }
}
Edit:
public class UriContainer
{
private string _uriMapper;
public string UriMapper { set { _uriMapper = value; } }
public int Id { get; set; }
public Uri SomeUri { get {return new Uri(_uriMapper);} }
}
public class DbTests
{
[Test]
public void Can_Get_A_Uri()
{
using (var c = new SqlConnection("hello"))
{
c.Open();
var uri = c.Query<UriContainer>("select *, someuri as urimapper from uris where id = 3").Single();
Console.WriteLine(uri.SomeUri);
}
}
}

Binding properties in two viewmodels in a two way manner

I'm starting Caliburn Micro development and I have thought of an architecture where a viewmodel has properties, injected by MEF, which are other viewmodels. That way I can use contentcontrols in the view to position them the way I want.
public class ContactsProfileViewModel : Conductor<IContentItem>, IContactsModuleViewModel, IModule, IPartImportsSatisfiedNotification
{
private string name;
private string nameCaption;
private ISingleLineTextContentItem firstName;
private ISingleLineTextContentItem lastName;
public ContactsProfileViewModel()
{
this.DisplayName = "Contact Tab";
}
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
this.NotifyOfPropertyChange(() => Name);
}
}
public string NameCaption
{
get
{
return this.nameCaption;
}
set
{
this.nameCaption = value;
this.NotifyOfPropertyChange(() => NameCaption);
}
}
[Import(typeof(ISingleLineTextContentItem))]
public ISingleLineTextContentItem FirstName
{
get { return this.firstName; }
set
{
this.firstName = value;
this.NotifyOfPropertyChange(() => FirstName);
}
}
[Import(typeof(ISingleLineTextContentItem))]
public ISingleLineTextContentItem LastName
{
get { return this.lastName; }
set
{
this.lastName = value;
this.NotifyOfPropertyChange(() => LastName);
}
}
The viewmodel of SingleLineTextContentItem looks like this:
[Export(typeof(ISingleLineTextContentItem))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class SingleLineTextContentItemViewModel : PropertyChangedBase, ISingleLineTextContentItem
{
private string textBoxText;
private string caption;
public string TextBoxText
{
get { return textBoxText; }
set
{
textBoxText = value;
this.NotifyOfPropertyChange(() => TextBoxText);
}
}
public string Caption
{
get { return caption; }
set
{
this.caption = value;
this.NotifyOfPropertyChange(() => Caption);
}
}
}
Now, I need a way to bind the NameCaption property to the Caption property in a two-way manner. Is that possible? I'm I on the right track with this or is there a better way to do this?
Thanks,
Roland
What I do is instead of having a backing field just route to the other view model
public string NameCaption
{
get
{
return FirstName.Caption;
}
set
{
FirstName.Caption = value;
this.NotifyOfPropertyChange(() => NameCaption);
}
}
However if the Caption property on the ISingleLineTextContentItem can get set independently then you need to register changes on the event and have the view model listen to changes. So instead you need somthing along the lines of:
public string NameCaption
{
get
{
return FirstName == null ? string.Empty : FirstName.Caption;
}
set
{
if(FirstName != null)
FirstName.Caption = value;
}
}
[Import(typeof(ISingleLineTextContentItem))]
public ISingleLineTextContentItem FirstName
{
get { return this.firstName; }
set
{
if(this.FirstName != null)
this.FirstName.PropertyChanged -= FirstNameChanged;
this.firstName = value;
if(this.FirstName != null)
this.FirstName.PropertyChanged += FirstNameChanged;
this.NotifyOfPropertyChange(() => FirstName);
this.NotifyOfPropertyChange(() => NameCaption);
}
}
private void FirstNameChanged(object sender, PropertyChangedEventArgs e)
{
if(e.PropertName == "Caption")
this.NotifyOfPropertyChange(() => NameCaption);
}
Since either the Caption property or the FirstName property can change then we need to raise the event in the FirstName property and in the handler.

property names are different from original Object in the silverlight

Following is part of service layer which is provided by WCF service :
[Serializable]
public class WaitInfo
{
private string roomName;
private string pName;
private string tagNo;
public string RoomName
{ get { return roomName; } set { this.roomName = value; } }
public string PName
{ get { return pName; } set { this.pName = value; } }
public string TagNo
{ get { return tagNo; } set { this.tagNo = value; } }
}
public class Service1 : IService1
{
public List<WaitInfo> GetWaitingList()
{
MyDBDataContext db = new MyDBDataContext();
var query = from w in db.WAIT_INFOs
select new WaitInfo
{
TagNo = w.PATIENT_INFO.TAG_NO,
RoomName= w.ROOM_INFO.ROOM_NAME,
PName= w.PATIENT_INFO.P_NAME
};
List<WaitInfo> result = query.ToList();
return result;
}
And following is codebehind part of UI layer which is provided by Silverlight
public MainPage()
{
InitializeComponent();
Service1Client s = new Service1Client();
s.GetWaitingListCompleted +=
new EventHandler<GetWaitingListByCompletedEventArgs>( s_GetWaitingListCompleted);
s.GetWaitingListAsync();
}
void s_GetWaitingListCompleted(object sender,
RadControlsSilverlightApplication1.ServiceReference2.GetWaitingListByCompletedEventArgs e)
{
GridDataGrid.ItemsSource = e.Result;
}
And following is xaml code in Silverlight page
<Grid x:Name="LayoutRoot">
<data:DataGrid x:Name="GridDataGrid"></data:DataGrid>
</Grid>
It is very simple code, however what I am thinking weird is property name of object at "e.Result" in the code behind page.
In the service layer, although properties' names are surely "RoomName, PName, TagNo", in the silverlight properties' names are "roomName, pName, tagNo" which are private variable name of the WaitingList Object.
Did I something wrong?
Thanks in advance.
Unless you specifically decorate your class with the DataContract attribute (which you should, instead of Serializable) then a default DataContract will be inferred. For normal Serializable types, this means the fields will be serialized as opposed to the properties.
You can markup your class in either of the following two ways. The latter will use the property accessors when serializing/deserializing your object which may be very useful or be a hassle depending on your circumstances.
[DataContract]
public class WaitInfo
{
[DataMember(Name="RoomName")]
private string roomName;
[DataMember(Name="PName")]
private string pName;
[DataMember(Name="TagNo")]
private string tagNo;
public string RoomName
{ get { return roomName; } set { this.roomName = value; } }
public string PName
{ get { return pName; } set { this.pName = value; } }
public string TagNo
{ get { return tagNo; } set { this.tagNo = value; } }
}
The method I prefer:
[DataContract]
public class WaitInfo
{
private string roomName;
private string pName;
private string tagNo;
[DataMember]
public string RoomName
{ get { return roomName; } set { this.roomName = value; } }
[DataMember]
public string PName
{ get { return pName; } set { this.pName = value; } }
[DataMember]
public string TagNo
{ get { return tagNo; } set { this.tagNo = value; } }
}

Resources