EntityWrapper Confusion - wpf

WPF
Entity Framework 6.0
Database first, entities are generated by TT file.
I'm having some problems with EntityWrapper, and can't find any useful information about it.
I have some entities, that when generated looks like this:
//generated code
public partial class scm_SupplierDepot : IPartsEntity, INotifyPropertyChanged
{
[...]
public virtual dms_Address dms_Address { get; set; }
}
public partial class dms_Address : IPartsEntity, INotifyPropertyChanged
{
//shortened for brevity
public System.Guid AddressId { get; set; }
public string StreetNumber { get; set; }
public string StreetName { get; set; }
public string ApartmentNumber { get; set; }
public string City { get; set; }
public string StateProvince { get; set; }
public string PostalCode { get; set; }
public string HouseName { get; set; }
public string Country { get; set; }
public string Address2 { get; set; }
public string County { get; set; }
//INotifyPropertyChanged
[..]
}
I extend the address class slightly with an interface:
public partial class dms_Address : IAddress { }
public interface IAddress
{
String StreetNumber { get; set; }
String StreetName { get; set; }
String ApartmentNumber { get; set; }
String Address2 { get; set; }
String City { get; set; }
String StateProvince { get; set; }
String PostalCode { get; set; }
String County { get; set; }
String Country { get; set; }
}
I am having some confusion and issues around getting the dms_Address entity from the scm_SupplierDepot entity. In most cases I can cast the Depot.dms_Address as IAddress and work with the entity with no issues.
But when I try binding this object to a Custom Control, the actual object that the control receives is a EntityWrapper< dms_Address > or EntityWrapperWithoutRelationships< dms_Address >
I had to make my control's dependency property accept an object, rather than an IAddress as I would prefer. Now I cannot work with the object as it will not cast to IAddress. I can't even cast it to EntityWrapper as I can't figure out the correct namespace to include.
public static readonly DependencyProperty AddressProperty = DependencyProperty.Register("Address", typeof(object), typeof(AddressForm), new FrameworkPropertyMetadata(null, AddressChanged));
public object Address
{
get { return (object)GetValue(AddressProperty); }
set { SetValue(AddressProperty, value); }
}
More information about my Custom Control and this Dependency Property issue can be read in a previous question: WPF Custom Control: DependencyProperty never Set (on only 1 of many properties)
Questions:
Can anyone explain to me what is going on here?
I don't understand where this wrapper is coming from. How can I make it go away?
How can I get the control to receive the IAddress instead of the wrapper?
Or how can I cast the EntityWrapper object to IAddress so I can access the properties in code? (oddly enough the template bindings work fine)

I figured out how to do what I needed by using Reflection.
Type objectType = Address.GetType();
Type iAdd = objectType.GetInterface("IAddress");
if (iAdd != null)
{
PropertyInfo info = objectType.GetProperty("StateProvince");
if (info != null)
{
string currentProvince = info.GetValue(Address) as string;
if (currentProvince != newValue)
info.SetValue(Address, newValue);
}
}
I am still stumped on why I'm seeing this behaviour; if it has the interface, why can't I cast it?
Type iAdd = Address.GetType().GetInterface("IAddress"); //iAdd is not null,
IAddress IA = (Address as IAddress); //IA is null
.
In the end I managed to switch my code around to make all of this code unnecessary >.<

Related

Change API response Object name (in Model) for Datagrid binding

I'm using WPF and still relatively new.
I haven't yet made the jump to MVVM, still trying to wrap my head around it.
I currently have a small app which extracts data from 4 different sources (at different times) and then displays it on a datagrid.
The issue is that the data model from the responses differs and I want to be able to easily use the same datagrid.
EG.
Datagrid binds to a model [zephyrPatientData]
Firstname : binds to firstName
last name: binds to lastName
ONE of the extractions has:
Firstname = firstName;
lastName = SURNAME.
Therefore if I use this data and try and bind to the datagrid, the LASTNAME firle is not filled as that model doesn't have lastName, it has surname.
Below: the datamodel that is working with the datagrid.
public class zephyrPatientData
{
public int CustomerID { get; set; }
public int ClaimID { get; set; }
public string ChemistID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string ClaimNumber { get; set; }
public bool concern { get; set; }
public int? InsCompID { get; set; }
public string InsCompName { get; set; }
public int? EmployerID { get; set; }
public string EmployerName { get; set; }
public string DateOfInjury { get; set; }
public string dateOfBirth { get; set; }
public string Address { get; set; }
public int? SuburbID { get; set; }
public string SuburbName { get; set; }
public string Postcode { get; set; }
public string custPhone { get; set; }
public int? claimTypeID { get; set; }
public string InvoiceTo { get; set; }
public string Comments { get; set; }
public string ClaimManager { get; set; }
public string Injury { get; set; }
public bool activeClaim { get; set; }
public string ClaimManagerEmail { get; set; }
public int? LawyerID { get; set; }
public string LawyerCompany { get; set; }
public double? outstandingScripts { get; set; }
public double? outstandingValue { get; set; }
public string dispenseConnected { get; set; }
public string dispenseID { get; set; }
}
Below: The Datamodel I want to work with the datagrid.
public class zDispensePatientData
{
public string id { get; set; }
public int clientNo { get; set; }
public string firstName { get; set; }
private string surname;
public string lastName
{
get
{
return surname;
}
set
{
surname = value;
}
}
public string title { get; set; }
public object licenseNo { get; set; }
public string sex { get; set; }
public object dateOfBirth { get; set; }
public object postalAddress { get; set; }
public object postalSuburb { get; set; }
public object postalState { get; set; }
public object postalPostCode { get; set; }
public string homeAddress { get; set; }
public string homeSuburb { get; set; }
public string homeState { get; set; }
public string homePostCode { get; set; }
public string phoneNumber { get; set; }
public string mobileNumber { get; set; }
public object faxNumber { get; set; }
public string email { get; set; }
public DateTime lastModified { get; set; }
public bool active { get; set; }
public bool deceased { get; set; }
}
As you can see...I TRIED to use the get;set; section of the [zDispensePatientData] however I have no idea how to use this correctly.
In reality in laman's terms I want it to read surname from the API response but then be accessible as lastName in for use in the Datagrid.
The reaons for this is that there will be another 4 [zDispensePatientData] (other names) and all will have different field names but in the end I need them to work in the same datagrid without changing the binding of every single datagrid column.
EDIT: Expanded the question:
So I appreciate the responses but I'm not exactly grasping how to get this done.
If I were to take away all the model fields and just leave... 3:
firstName
lastName
patientID
my task is to have 5 different models (from responses from API's) 'allocate' to my own model.
eg.
<my model>
public string id { get; set; }
public string lastName { get; set; }
public string firstName { get; set; }
<model API 1>
public string id { get; set; }
public string patientLastName { get; set; }
public string patientFirstName { get; set; }
<model API 2>
public string patientid { get; set; }
public string surname{ get; set; }
public string FIRSTNAME{ get; set; }
Any app will only ever have one connection ([dispenseType]).
So I guess what I need is checking the user dispenseType and then using the model from the API they are using.
Or is it possible to SET myModel based on the contents of the other models.
eg.
if
API1.firstName = null
myModel.firstName = api2.FIRSTNAME
My main issue is I don't know the concept or question to ask. If there is a pointer to the terminology of what I'm trying to achieve I'm happy to go out and learn it to implement it.
If the column in the DataGrid binds to a property named "LastName", you need to make sure that the type T in the IEnumerable<T> ItemsSource of the DataGrid has such a property.
So add one to the zDispensePatientData class like you have currently done:
public string LastName
{
get => surname;
set => surname = value;
}
Another option is to set or bind the ItemsSource to a an IEnumerable<ViewModel> where the ViewModel class has the properties that the DataGrid expects.
You would then translate each zephyrPatientData and/or zDispensePatientData object to a ViewModel, e.g.:
sourceCollection = zDispensePatientDatas
.Select(x => new ViewModel() { LastName = x.Surname } );
How to map properties of two different objects?
This question answers my question but was stated in a better way than I could

AutoMapper with Array and JsonApiSerializer.JsonApi.Relationship

I have an AppService solution with the following Classes and i want to map from the SourceObject to the DestinationObject
Source Classes
public class SourceObject
{
public string Id { get; set; }
public string Name { get; set; }
public JsonApiSerializer.JsonApi.Relationship<SourceChildObject[]> childObjects { get; set; }
}
public class SourceChildObject
{
public string Id { get; set; }
public string type { get; set; }
}
Destination Classes
public class DestinationObject
{
public string Id { get; set; }
public string Name { get; set; }
public JsonApiSerializer.JsonApi.Relationship<DestinationChildObject[]> childObjects { get; set; }
}
public class DestinationChildObject
{
public string Id { get; set; }
public string type { get; set; }
}
Auto mapper is setup in the sartup class
services.AddAutoMapper(typeof(EntityMappingProfile));
And my mapping class loos like this
public class EntityMappingProfile : Profile
{
public EntityMappingProfile()
{
CreateMap<SourceObject, DestinationObject>();
CreateMap<Relationship<SourceChildObject[]>, Relationship<DestinationChildObject[]>>();
}
}
When i execute the solution all fields are mapped apart form the array field of type JsonApiSerializer.JsonApi.Relationship. The destination field is null. What am i doing wrong?
You forgot about creating a map between SourceChildObject and DestinationChildObject. Add this line to your EntityMappingProfile.
CreateMap<SourceChildObject, DestinationChildObject>();
And one more thing, when you are mapping generic types, you can enable mapping for all types with:
CreateMap(typeof(Relationship<>), typeof(Relationship<>));
instead of creating a map with concrete use case of a generic type.

Business Rule errors not going away when data is valid

I am using Orc.FluentValidation and I have:
[ValidatorDescription(nameof(Customer), ValidationResultType.Error,
Orc.FluentValidation.ValidationType.BusinessRule)]
public class CustomerBusinessRuleValidator : AbstractValidator<Customer>
{
public CustomerBusinessRuleValidator()
{
RuleFor(x => x.Addresses).Must(x => x != null && x.Count > 0 && x.Any(add => add.IsCurrent))
.WithMessage("Customer object is required to have at least 1 current address.");
}
}
CustomerAddress
public class CustomerAddress : Entity
{
[DomainSignature] public Address Address { get; set; }
[DomainSignature] public Lookup AddressType { get; set; }
[DomainSignature] public bool IsCurrent { get; set; }
}
Customer
public class Customer : Entity
{
[DomainSignature]
public string Code { get; set; }
public Gender Gender { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public DateTime DateOfBirth { get; set; }
public Lookup PlaceOfBirth { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public ICollection<CustomerAddress> Addresses { get; set; }
public Lookup Occupation { get; set; }
public IdDocument Id1 { get; set; }
public IdDocument Id2 { get; set; }
}
On the View even after a CustomerAddress with IsCurrent = true is added for the Customer, the message still shows. Also, I am not sure why some field-bound controls show the error and others not _this is not a field validation rule.
Is there like a method call to be done after adding the CustomerAddress to the Addresses collection?
i.imgur.com/eecAFuJ.png
Make sure you raise a property changed on the whole collection for error validation (e.g. RaisePropertyChanged(nameof(MyCollection)), otherwise the UI can't update the validation results.
Also, I am not sure why some field-bound controls show the error and
others not _this is not a field validation rule.
This is probably because of the default styles you are using. For most of the controls, Orchestra creates an error template (decorator), but not every control had this. We've been working on adding these last week, so I recommend to try out the latest alpha of Orchestra & Orc.Controls.
Also make sure to set ValidateOnDataErrors and NotifyOnValidationErrors on the binding to show the validation in the UI.

Serialize complex properties with Dapper

Is it possible to make Dapper.NET serialize complex properties with Json.NET? The object should be serialized and then stored into a column as string:
public class Person
{
public string Id { get; set; }
public Address Address { get; set; } // store this as string in database
...
}
public class Address
{
public string City { get; set; }
public string ZipCode { get; set; }
}
Right now we do this manually using ADO.NET:
command.Parameters.AddWithValue("#Id", obj.Id);
command.Parameters.AddWithValue("#Address", obj.Address != null ? JsonConvert.Serialize(obj.Address) : (object) DBNull.Value);
...

Asp.net mvc using EntityFramework: loading Person by passing id is retrieving a Object but Object properties are null?

i am hanging for while and i dont understand one thing...I will try to explain my issue...
I have model(Table) called FeuerwehrPerson and the class looks like that:
public partial class FeuerwehrPerson
{
public FeuerwehrPerson()
{
this.BuchungenResultateList = new List<BuchungenResultate>();
this.Notenspiegel=new Notenspiegel();
this.Gemeinde=new Gemeinde();
}
public int FeuerwehrPersonId { get; set; }
public string Anrede { get; set; }
public string Vorname { get; set; }
public string Nachname { get; set; }
public System.DateTime Geburtstag { get; set; }
public string Strasse { get; set; }
public string Plz { get; set; }
public string Ort { get; set; }
public string Telefon { get; set; }
public int GemeindeId { get; set; }
public Nullable<int> NotenspielgelId { get; set; }
public virtual ICollection<BuchungenResultate> BuchungenResultateList { get; set; }
public virtual Gemeinde Gemeinde { get; set; }
public virtual Notenspiegel Notenspiegel { get; set; }
}
In Feuerwehrperson are 2 Foreign Keys
GemeindeId
NotenspiegelId
and both of them are holding some values for a specific FeuerwehrPerson.
Both Foreign Keys are not null in my FeuerehrPerson Table...
In my Controller i have a Edit Action...and i am searching for FeuerwehrPerson by id...thats working fine:
FeuerwehrPerson feuerwehrperson = db.FeuerwehrPerson.Find(id);
When i am checking the values by using add Watch of feuerwehrperson Object there are some empty properties which shouldn´t be empty
The Object property Gemeinde should contain some values but its empty...also for Notenspiegel Object should contain SeminarA=true, SeminarB=true, SeminarC=true, rest is false but everything is false also NotenspiegelId and GemeindeId...but the Foreign Key references in Feuerwehrperson are not null...but why is it empty????
Please help me...

Resources