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.
Related
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
When I do an insert using EF6, I get this error
The column name 'employee_id' is specified more than once in the SET clause. A column cannot be assigned more than one value in the same SET clause. Modify the SET clause to make sure that a column is updated only once. If the SET clause updates columns of a view, then the column name 'employee_id' may appear twice in the view definition
My models looked like this:
public class Entity
{
public Entity()
{
IsActive = true;
IsDeleted = false;
DateCreated = DateTime.Now;
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long ID { get; set; }
public int CompanyID { get; set; }
public int SubID { get; set; }
public DateTime DateCreated { get; set; }
public bool IsTransient()
{
return EqualityComparer<long>.Default.Equals(ID, default(long));
}
public bool IsDeleted { get; set; }
public bool IsActive { get; set; }
}
public partial class NextOfKin : Entity
{
[Required]
public long employee_id { get; set; }
[StringLength(100)]
[Required]
public string nok_first_name { get; set; }
[StringLength(100)]
[Required]
public string nok_last_name { get; set; }
[StringLength(300)]
[Required]
public string nok_address { get; set; }
[StringLength(100)]
public string nok_email { get; set; }
[StringLength(100)]
public string nok_phone { get; set; }
[StringLength(100)]
public string nok_employer { get; set; }
[StringLength(300)]
public string nok_work_address { get; set; }
[StringLength(100)]
[Required]
public string nok_relationship { get; set; }
public virtual Employee Employee { get; set; }
}
public class Employee : Entity
{
//Person Records
public long UserId { get; set; }
public int TitleId { get; set; }
public int? ReligionId { get; set; }
public string SerialNo { get; set; }
[StringLength(100)]
[Required]
public string FirstName { get; set; }
[StringLength(100)]
[Required]
public string LastName { get; set; }
}
My insert code into next of kin was like this.
NextOfKin nextOfKin = new NextOfKin();
nextOfKin.employee_id = newEmployee.ID;
nextOfKin.nok_first_name = "Friday";
nextOfKin.nok_last_name = "Ben";
nextOfKin.nok_address = "XXX";
nextOfKin.nok_email = "xa#xo.com";
nextOfKin.nok_phone = "023938494";
nextOfKin.nok_employer = "50 Queens Street";
nextOfKin.nok_work_address = "51 Queens Street";
nextOfKin.nok_relationship = "Neighbour";
db.NextOfKins.Add(nextOfKin);
db.SaveChanges();
I got an error like this using EF Core
'PropertyNameID' is specified more than once in the SET clause or
column list of an INSERT. A column cannot be assigned more than one
value in the same clause. Modify the clause to make sure that a column
is updated only once. If this statement updates or inserts columns
into a view, column aliasing can conceal the duplication in your code.
It turned out that I had the case wrong in my relatonship
In My business object I had the foreign key set with the wrong case.
public int PropertyNameID { get; set; }
[ForeignKey("PropertyNameId")] public virtual PropertyNameExt PropertyName { get; set; }
Should have been
[ForeignKey("PropertyNameID")] public virtual PropertyNameExt PropertyName { get; set; }
To fix this, remove the relationship on next of kin model, then do migration.
To remove, remove public virtual Employee Employee { get; set; } from NextOfKin model.
The reason for this issue is as follow:
Relationships are only created properly if you name the reference property properly. In this case you should use EmployeeID instead of employee_id for the relationship between next of kin and employee.
The Employee model does not have a link back to the next of kin model. If it's a one to many you can add the property below to the Employee model.
public virtual List NextOfKins{get; set;} //if you need lazy loading
or
public List NextOfKins{get; set;} //if you don't need lazy loading
How to include/populate a navigation property with custom(1-to-1) query in EF?
e.g.
public class Item {
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Id")]
public ItemCost LatestCost {get; set; }
}
public class ItemCost {
public int Id { get; set; }
public DateTime From { get; set; }
public DateTime? To { get; set; }
public decimal Cost { get; set; }
}
Goal is to populate the LatestCost property of the Item with it's latest cost from ItemCosts. How is this being accomplished with EF or what's your take on this?
Is it possible to do a custom query within .Include/.ThenInclude methods?
e.g.
.ThenInclude(a => { a.LatestCost = (from a _db.ItemCosts
where... select a).SingleOrDefault() })...
You could use a virtual get-only property. Your nav property should really be an ICollection<ItemCost>. In this example I'm assuming the Id property in the ItemCost class is the id of the related Item, but it's not clear. Tip: using nameof(property) instead of hard-coding the property name will allow the compiler to catch errors with the name if you were to change it for some reason. The [NotMapped] attribute tells Entity Framework to not try and map the property to a database field.
public class Item {
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ItemCost> ItemCosts {get; set; }
[NotMapped]
public virtual ItemCost LatestCost
{
get
{
return ItemCosts.OrderByDescending(x => x.From).FirstOrDefault();
}
}
}
public class ItemCost {
public int Id { get; set; }
public DateTime From { get; set; }
public DateTime? To { get; set; }
public decimal Cost { get; set; }
[ForeignKey(nameof(Id))]
public virtual Item Item { get; set; }
}
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 >.<
public class Employee {
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public decimal Salary { get; set; }
public string Email { get; set; }
}
public class EmployeeContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
}
When I'm adding Data Annotation [Required(ErrorMessage = "Employee Name is required")] to the Name property it's throwing an InvalidOperationException. As I was trying to fix the bug I'm getting these suggestions online:
It means one of your classes use in the EmployeeContext has changed, but the database hasn't been updated so is now out of date. You need to update this use Code First migrations.
When I'm making the following changes its throwing an error now
public class Employee {
[Key]
public int Id { get; set; }
[DisplayName("Employee Name")]
[Required(ErrorMessage = "Employee Name is required")]
[StringLength(35)]
public string Name { get; set; }
public string Address { get; set; }
public decimal Salary { get; set; }
public string Email { get; set; }
}
Snapshot:
Questions:
If a Database Table is created is it possible to change a column ?
When adding a Data Annotation Attribute it's throwing an Exception, why is the database table column not changing ?
Addicted to your tutorials now
User Migration for update database structure
Without [Required] filed Name allow null (varchar(x) null), with [Required] Name change not null (varchar(x) not null)
If in database threre are rows with nullable Name, can be error on update (with migration)