Changing a model without altering the database? - c#

I've got a model being used to populate a database
public class Account
{
public int NumberOfPayPeriods { get { return 24; } }
public decimal YearAmount { get; set; }
public decimal PlanTotal
{
get { return NumberOfPayPeriods*YearAmount; }
}
}
The NumberOfPayPeriods attribute I need to change from just a get to a get; set;
However, when I change this, I get an EntityCommandExecutionException (invalid column name). I assume this is because it is trying to map this to the database where there previously existed no such column (as it was only a get).
Is there any way I can change this to a get;set; without having to delete the table? There's a lot of important data on there that cannot be lost or re-created.

Add a [NotMapped] attribute over the property you don't want stored.
public class Account
{
[NotMapped]
public int NumberOfPayPeriods { get { return 24; } set { ... } }
public decimal YearAmount { get; set; }
public decimal PlanTotal
{
get { return NumberOfPayPeriods*YearAmount; }
}
}

Related

Assigning [NotMapped] property value after "regular" (mapped) property value has been assigned

Is there a way to assign a value to a not mapped property after all mapped properties get their values from the DB? For example:
public class ProcessSupervisor
{
public int ID { get; set; }
public int MaximumConcurrentProcesses { get; set; }
[NotMapped]
public int AvailableProcessSlots { get; set; }
}
I would like to keep the value of MaximumConcurrentProcesses in the database and assign that value to AvailableProcessSlots as a default value once Entity Framework instantiates ProcessSupervisor DBSet and assigns corresponding values to objects properties. Obviously I cannot assign the value of MaximumConcurrentProcesses to AvailableProcessSlots in class constructor since MaximumConcurrentProcesses hasn't received it's value from database yet. Is there a proper way do do it without initializing the AvailableProcessSlots value in some weird and awkward way?
You can try something like this:
public class ProcessSupervisor
{
public int ID { get; set; }
public int MaximumConcurrentProcesses { get; set; }
[NotMapped]
private int? availableProcessSlots = null;
public int AvailableProcessSlots
{
get
{
return availableProcessSlots ?? MaximumConcurrentProcesses;
}
set
{
availableProcessSlots = value;
}
}
}

ASP.NET C# Class/Object with default values and database NOT NULL columns

I am using SQL server for database while developing in ASP.NET . In my database table, most of the columns are NOT NULL and have a set default value. I am also using Entity Framework.
My Model(class) currently looks like this:
public partial class INV
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public INV()
{
this.INVAttachments = new HashSet<INVAttachment>();
}
public int ID { get; set; }
public string SUPPROD { get; set; }
public string TYPE1 { get; set; }
public int MAXQTY { get; set; }
public decimal ROP { get; set; }
public int ROQ { get; set; }
public decimal SSL { get; set; }
public Nullable<System.DateTime> SYSDATE { get; set; }
public Nullable<System.DateTime> MAINT_DATE { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public ICollection<INVAttachment> INVAttachments { get; set; }
}
The user submits a form, and inside the form, most of fields are actually optional. But in the database, the columns are not null.
When I POST the form over to the server side, the INV object representation has null for the properties of the INV object. Below is a WebAPI function to handle the POST and save the INV object in the database.
[ResponseType(typeof(string))]
public async Task<string> PostINV(INV iNV)
{
try
{
if (!ModelState.IsValid)
{
//return BadRequest(ModelState);
return "badRequest";
}
db.INVs.Add(iNV);
await db.SaveChangesAsync();
//codes written here
}catch (Exception ex)
{
return "";
}
}
The above function is now returning system.data.entity.validation.dbvalidationerror for the INV entity because the properties for INV is required, but the object that I POST over contain NULL values.
My question is it possible to make sure the database columns remain NOT NULL but at the same time, I don't want my Model or Class to use Nullable types? Is it a matter of using a constructor for my class to set default values ?
This is just an answer to your question in a comment, and may not be the best solution
how does one make up values for DB ? Is it done by defining a
constructor or a method on the model?
You can do it a number of ways, however this is a very simple solution
public class Track
{
public Track()
{
LengthInMeters = 400;
}
public int LengthInMeters { get; set; }
}

Entity Framework reference property

I am working with Entity Framework 6.
I am working with 2 classes:
public partial class StateProvince
{
public StateProvince()
{
Addresses = new HashSet<Address>();
}
public int StateProvinceID { get; set; }
public string StateProvinceCode { get; set; }
public string CountryRegionCode { get; set; }
public bool IsOnlyStateProvinceFlag { get; set; }
public string Name { get; set; }
public int TerritoryID { get; set; }
public Guid rowguid { get; set; }
public DateTime ModifiedDate { get; set; }
public ICollection<Address> Addresses { get; set; }
public CountryRegion CountryRegion { get; set; }
}
public partial class CountryRegion
{
public CountryRegion()
{
StateProvinces = new HashSet<StateProvinceTlb>();
}
public string CountryRegionCode { get; set; }
public string Name { get; set; }
public DateTime ModifiedDate { get; set; }
public virtual ICollection<StateProvince> StateProvinces { get; set;}
}
I would like to be able to run a query that would return a list of StateProvince, but also include the name from CountryRegion. The idea is that on an edit screen, the user will select, or edit the CountryRegionCode, but the Name will display beside it in a none editable field just for reference.
I tried adding property as a none mapped field to StateProvince and referencing the property on CountryRegion, like below:
[NotMapped]
public string CountryName
{
get{ return CountryRegion.Name;}
}
but the problem with this is the CountryRegion has to be loaded in order for that to work, and my goal is to not have to load the entire CountryRegion object.
I've also tried to set it in my query like this:
List<StateProvince> statP = context.StateProvinces.Select(s => new StateProvince() {s, CountryName = context.CountryRegions.Where(x => x.CountryRegionCode == s.CountryRegionCode).Select(x => x.Name).FirstOrDefault() }).ToList();
but this doesn't work because the object returned is comprised of a StateProvince object and a separate CountryName property.
I've even tried setting each of the fields individually like:
List<StateProvince> statP = context.StateProvinces.Select(s => new StateProvince() { Name = s.Name, TerritoryID = s.TerritoryID, rowguid = s.rowguid, ModifiedDate = s.ModifiedDate, Addresses=s.Addresses, CountryRegion=s.CountryRegion, CountryName = context.CountryRegions.Where(x => x.CountryRegionCode == s.CountryRegionCode).Select(x => x.Name).FirstOrDefault() }).ToList();
But this again causes the entire CountryRegion object to load, and if I leave those properties out, an exception is thrown. Also, for larger entities this will be hard to maintain.
The TLDR; version of this: Is there a way in Entity Frameworks to have a class mapped to one table, but have a property on that class that references a property on another table without having to retrieve everything on the child table?
I've searched and searched and can't really find much covering this specific kinda of scenario. I'm fairly new to Entity Framework, and I feel like I'm missing something obvious. Any help would be greatly appreciated!!
SOLUTION
This is what I've come up with to solve the issue.
First, I split the CountryRegion table into two separate classes
public partial class CountryRegionHeader
{
public CountryRegionHeader()
{
StateProvinces = new HashSet<StateProvinceTlb>();
}
public string CountryRegionCode { get; set; }
public string Name { get; set; }
}
public partial class CountryRegionDetail
{
public CountryRegionDetail()
{
StateProvinces = new HashSet<StateProvinceTlb>();
}
public string CountryRegionCode { get; set; }
public DateTime ModifiedDate { get; set; }
public virtual ICollection<StateProvince> StateProvinces { get; set;}
public virtual CountryRegion CountryRegion {get;set;}
}
I then add the properties for the new classes to my StateProvince class
[ForeignKey("CountryRegionCode)]
public CountryRegionHeader CountryRegionHeader {get;set;}
[ForeignKey("CountryRegionCode)]
public CountryRegionDetail CountryRegionDetail {get;set;}
I then add the DBSets to my model context for CountryRegionHeader and CountryRegionDetail and tie them together using the fluent API in the OnModelCreating method
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<CountryRegionHeader>()
.HasRequired(e => e.CountryRegionDetail)
.WithRequiredPrincipal();
}
In addition to this, I've created another class just called CountryRegion which has all of the properties from both the Header and Detail as well as the Header and Detail object themselves. The properties actually point back to the header and detail. This really isn't necessary, but it makes the code cleaner and easier to use. Also, when sending the data down to a web client I can just serialize the CountryRegion object and exclude the Header and Detail object. So basically my CountryRegion class looks like this:
public Class CountryRegion
{
public CountryRegionHeader Header;
public CountryRegionDetail Detail;
public CountryRegionCode
{
//need some special logic here for the key since both Header or
//Detail share the primary key and both may not be loaded
get
{
if (Header != null)
return Header.CountryRegionCode;
else
return Detail.CountryRegionCode;
}
set
{
if (Header != null) Header.CountryRegionCode = value;
if (Detail != null) Detail.CountryRegionCode = value;
}
}
public string Name
{
get
{
return Header.Name;
}
set
{
Header.Name = value;
}
}
public DateTime ModifiedDate
{
get
{
return Detail.ModifiedDate ;
}
set
{
Detail.ModifiedDate = value;
}
}
public virtual ICollection<StateProvince> StateProvinces
{
get
{
return Detail.StateProvinces ;
}
set
{
Detail.StateProvinces = value;
}
}
}
So, Now When I query I can do something like:
List<StateProvince> query = db.StateProvince.Include(o=>o.CountryRegionHeader).ToList();
And I only retrieve the data I need without retrieving the entire CountryRegion record
Also, If I'm working with just the CountryRegion, I can query like this:
List<CountryRegion> query = (from a in db.CountryRegionHeader join b in db.CountryRegionDetail on a.CountryRegionCode equals b.CountryRegionCode select new Employee(){Header = a, Detail = b}).ToList();
SOLUTION
This is what I've come up with to solve the issue.
First, I split the CountryRegion table into two separate classes
public partial class CountryRegionHeader
{
public CountryRegionHeader()
{
StateProvinces = new HashSet<StateProvinceTlb>();
}
public string CountryRegionCode { get; set; }
public string Name { get; set; }
}
public partial class CountryRegionDetail
{
public CountryRegionDetail()
{
StateProvinces = new HashSet<StateProvinceTlb>();
}
public string CountryRegionCode { get; set; }
public DateTime ModifiedDate { get; set; }
public virtual ICollection<StateProvince> StateProvinces { get; set;}
pubic virtual CountryRegion CountryRegion {get;set;}
}
I then add the properties for the new classes to my StateProvince class
[ForeignKey("CountryRegionCode)]
public CountryRegionHeader CountryRegionHeader {get;set;}
[ForeignKey("CountryRegionCode)]
public CountryRegionDetail CountryRegionDetail {get;set;}
I then add the DBSets to my model context for CountryRegionHeader and CountryRegionDetail and tie them together using the fluent API in the OnModelCreating method
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<CountryRegionHeader>()
.HasRequired(e => e.CountryRegionDetail)
.WithRequiredPrincipal();
}
In addition to this, I've created another class just called CountryRegion which has all of the properties from both the Header and Detail as well as the Header and Detail object themselves. The properties actually point back to the header and detail. This really isn't necessary, but it makes the code cleaner and easier to use. Also, when sending the data down to a web client I can just serialize the CountryRegion object and exclude the Header and Detail object. So basically my CountryRegion class looks like this:
public Class CountryRegion
{
public CountryRegionHeader Header;
public CountryRegionDetail Detail;
public CountryRegionCode
{
//need some special logic here for the key since both Header or
//Detail share the primary key and both may not be loaded
get
{
if (Header != null)
return Header.CountryRegionCode;
else
return Detail.CountryRegionCode;
}
set
{
if (Header != null) Header.CountryRegionCode = value;
if (Detail != null) Detail.CountryRegionCode = value;
}
}
public string Name
{
get
{
return Header.Name;
}
set
{
Header.Name = value;
}
}
public DateTime ModifiedDate
{
get
{
return Detail.ModifiedDate ;
}
set
{
Detail.ModifiedDate = value;
}
}
public virtual ICollection<StateProvince> StateProvinces
{
get
{
return Detail.StateProvinces ;
}
set
{
Detail.StateProvinces = value;
}
}
}
So, Now When I query I can do something like:
List<StateProvince> query = db.StateProvince.Include(o=>o.CountryRegionHeader).ToList();
And I only retrieve the data I need without retrieving the entire CountryRegion record
Also, If I'm working with just the CountryRegion, I can query like this:
List<CountryRegion> query = (from a in db.CountryRegionHeader join b in db.CountryRegionDetail on a.CountryRegionCode equals b.CountryRegionCode select new Employee(){Header = a, Detail = b}).ToList();
One way to achieve this is to add a computed column on your database that gives you the CountryRegion name on your StateProvince.
With this all you have to do is to request the StateProvince table and your database server will give you the relevant associated CountryRegion name.
Edit
After your comment I had another idea.
Create a class for your usage :
public class StateProvinceEdition : StateProvince
{
public string CountryRegionName { get; set; }
public StateProvinceEdition(StateProvince stateProvince, string countryRegionName)
{
this.StateProvinceID = stateProvince.StateProvinceID;
// And so on ...
// Adding country region name
this.CountryRegionName = countryRegionName;
}
}
Then you need to project your query result into your object using Linq :
List<StateProvinceEdition> statP = context.StateProvinces.Select(s => new StateProvince(s, s.CountryRegion.Name)).ToList();
I do not have a database to test it upon so if EF throws an exception regarding the constructor, try to switch the Select and ToList statements to first load objects from the database and then project the result in the custom class.
Second edit
Similar to the first idea, you can create a view in your database for your purpose and then use Entity Framework to query this view. With this solution you do not need to change your database other than adding a view.

ViewModel properties for properties of nested classes inside the model

I have an application following the MVVM pattern, that has to serialize XML files. As some of the XML attributes are nested, I've created nested classes inside my Model, like this:
public class OPER_FILE
{
public UNB unb { get; set; }
public OPER oper { get; set; } //nested class, level 1
public OPER_FILE()
{
unb = new UNB();
oper = new OPER();
}
}
public class OPER
{
public UNH unh { get; set; } //these are all nested classes, level 2
public UVT uvt { get; set; }
public VIN vin { get; set; }
public OPER()
{
unh = new UNH();
uvt = new UVT();
}
}
#region "nested classes"
public class UNB
{
public string unb { get; set; }
public string unb_2 { get; set; }
}
public class UNH
{
public string unh { get; set; }
public string unh_2 { get; set; }
}
public class UVT
{
public string uvt { get; set; }
public string uvt_1 { get; set; }
public string uvt_2 { get; set; }
}
public class VIN
{
public string vin { get; set; }
public string vin_1 { get; set; }
public string vin_2 { get; set; }
public string vin_3 { get; set; }
public string vin_4 { get; set; }
}
#endregion
The attributes of the nested classes are all strings, because this simplifies the XML serialization for now (I'm still in the conception phase).
In my corresponding ViewModel, I've simply created a property for the nested class inside the model, so I can access all of the nested properties with just referring to this nested class from the ViewModel.
public class OPERViewModel : IViewModelBase
{
private OPER_FILE Model;
public UNB unb
{
get
{ return Model.unb;}
set
{ Model.unb = value; }
}
public OPER oper
{
get
{ return Model.oper; } //this is the tricky part, by now I'm just referring to the nested class as a property of the model
set
{ Model.oper = value; }
}
public OPERViewModel()
{ Model = new OPER_FILE(); }
}
The question is, however, that I want to display some of the properties not as strings but as boolean values using checkboxes on the UI.
Saying I want to display Model.oper.vin.vin_1 as boolean (where the ViewModel should manage the conversion from string to bool in the getter of its own property reflection of Model.oper.vin.vin_1), how would I do that?
Would I really have to implement every nested property from a nested class as an own property of the ViewModel (like stated below) to gain control over the way it will be returned to the UI?
//ViewModel-implementation with type-conversion of a property from a nested class of the model
//this would get bind to the UI instead of Model.oper.vin.vin_1
public bool vin_1
{
get
{
if (Model.oper.vin.vin_1 == "1")
{ return true; }
else
{ return false; }
}
set
{
if (value)
{ Model.oper.vin.vin_1 = "1"; }
else
{ Model.oper.vin.vin_1 = "0"; }
}
}
I hope there is a better solution out there...
Edit:
What I forgot to mention before, there're not only strings that have to be displayed as booleans, also DateTime-values that should be displayed as a DatePicker-control, integer-values that I would like to have as NumberPickers and so on.
The xml-file, on the other hand, will be consumed by an interface with some pretty fixed regulations that i need to match, such a dynamically leading zeros on both integer- and float-values, special date formats and commas instead of dots as decimal separators. So sticking with the string-values inside the object to serialize is a good way of maintaining control over how the values would get actually parsed inside the xml-file.
I'll try and experiment with some different converters, as #BrandlyDOTNet reommended, but are still curious about how this could be solved in another way.
There's a different solution out there, namely that you can use a converter to define the translation between your strings and a bool.
Something like:
public class StringToBoolConverter : IValueConverter
{
public object Convert(...)
{
return value.ToString() != "0";
}
public object ConvertBack(...)
{
bool boolVal = (bool)value;
return boolVal ? "1" : "0";
}
}
Usage:
<CheckBox IsChecked={Binding SomeProp, Converter={StaticResource StringToBoolConverter}"/>
But to answer your deeper question, no, the framework will not just convert the string "1" into a bool. Moreover, you can strongly type your object that is being serialized, so none of this is actually necessary.

C# Mapping struct in ActiveRecord

i am making a little application to help me balance my checkbook.
i am using Castle ActiveRecord to map the object properties to the database. now here is the problem. as i am making a money program i made a struct Currency
The struct:
public struct Currency
{
private long amount;
private CurrencyType currencyType;
public long Amount
{
get { return this.amount; }
set { this.amount = value; }
}
public CurrencyType CurrencyType
{
get { return this.currencyType; }
set { this.currencyType = value; }
}
}
The class i am mapping:
[ActiveRecord("[Transaction]")]
public class Transaction: HasOwnerModelBase
{
private Currency amount;
private Category category;
[BelongsTo]
public virtual Category Category
{
get { return this.category; }
set { this.category = value; }
}
public virtual Currency Amount
{
get { return this.amount; }
set { this.amount = value; }
}
}
Now in the ideal situation the Currency object would act like a nested object so the amount and currencyType are two colums in the transaction table.
but it is not a nested seeing as i want it to act like the currency struct object.
I have no idea what tag i should give the Currency Amount for it to work, i would really appreciate it if any one could help me solve this problem.
I hope all of this is clear.
Greatings Duncan
What about the following? Or didn't I get the question? Note that I changed the structure to a class because you need virtual members for dynamic proxy generation and you cannot have virtual members on structures. By the way, why don't you use auto-implemented properties?
public class Currency
{
[Property]
public virtual Int64 Amount { get; set; }
[Property]
public virtual CurrencyType CurrencyType { get; set; }
}
[ActiveRecord("[Transaction]")]
public class Transaction: HasOwnerModelBase
{
[BelongsTo]
public virtual Category Category { get; set; }
[Nested]
public virtual Currency Amount { get; set; }
}

Categories