Entity Framework Code First: NULL values inserted in database - c#

I am using Entity Framework Code First Approach. I have following code to insert data into PaymentComponent and Payment tables. The data getting inserted into PaymentComponent table is not proper. It has NULL values in two columns (for one record) even though the corresponding properties in the domain objects are not null. What need to be changed in order to make it working?
EDIT
When I added the following in NerdDinners class, I am getting following result - it has new unwanted columns
public DbSet<ClubCardPayment> ClubCardPayments { get; set; }
ORIGINAL CODE
static void Main(string[] args)
{
string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
using (var db = new NerdDinners(connectionstring))
{
GiftCouponPayment giftCouponPayment = new GiftCouponPayment();
giftCouponPayment.MyValue=250;
giftCouponPayment.MyType = "GiftCouponPayment";
ClubCardPayment clubCardPayment = new ClubCardPayment();
clubCardPayment.MyValue = 5000;
clubCardPayment.MyType = "ClubCardPayment";
List<PaymentComponent> comps = new List<PaymentComponent>();
comps.Add(giftCouponPayment);
comps.Add(clubCardPayment);
var payment = new Payment { PaymentComponents = comps, PayedTime=DateTime.Now };
db.Payments.Add(payment);
int recordsAffected = db.SaveChanges();
}
}
DOMAIN CODE
public abstract class PaymentComponent
{
public int PaymentComponentID { get; set; }
public abstract int MyValue { get; set; }
public abstract string MyType { get; set; }
public abstract int GetEffectiveValue();
}
public partial class GiftCouponPayment : PaymentComponent
{
private int couponValue;
private string myType;
public override int MyValue
{
get
{
return this.couponValue;
}
set
{
this.couponValue = value;
}
}
public override string MyType
{
get
{
return this.myType;
}
set
{
this.myType = value;
}
}
public override int GetEffectiveValue()
{
if (this.PaymentComponentID < 2000)
{
return 0;
}
return this.couponValue;
}
}
public partial class ClubCardPayment : PaymentComponent
{
private int cardValue;
private string myType;
public override int MyValue
{
get
{
return this.cardValue;
}
set
{
this.cardValue = value;
}
}
public override string MyType
{
get
{
return this.myType;
}
set
{
this.myType = value;
}
}
public override int GetEffectiveValue()
{
return this.cardValue;
}
}
public partial class Payment
{
public int PaymentID { get; set; }
public List<PaymentComponent> PaymentComponents { get; set; }
public DateTime PayedTime { get; set; }
}
//System.Data.Entity.DbContext is from EntityFramework.dll
public class NerdDinners : System.Data.Entity.DbContext
{
public NerdDinners(string connString): base(connString)
{
}
protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public DbSet<GiftCouponPayment> GiftCouponPayments { get; set; }
public DbSet<Payment> Payments { get; set; }
}
REFERENCE:
When using entity framework code-first mapping property to separate table, moves foreign key field
Override Entity Framework Entity Property
EntityFramework how to Override properties
http://weblogs.asp.net/manavi/archive/2011/04/24/associations-in-ef-4-1-code-first-part-4-table-splitting.aspx
http://www.robbagby.com/entity-framework/entity-framework-modeling-entity-splitting/
Entity Framework Mapping Scenarios - http://msdn.microsoft.com/en-us/library/cc716779.aspx
http://blogs.microsoft.co.il/blogs/gilf/archive/2009/03/06/entity-splitting-in-entity-framework.aspx

Implement MyType and MyValue directly in the base class. EF allows shared members to be implemented only in the base class. Members implemented in derived class use their own columns in the resulting table.

you haven't defined the ClubCardPayment dbset in the datacontext.
insert this and it should work
public DbSet<ClubCardPayment> ClubCardPayments { get; set; }

You need to define the 2 classes that are actually implements of the abstract class, that's the only way EF will know the different classes and how to read/update/write instances of them.
(No need to map the abstract class in EF!).

This doesn't contribute to your question, but just a hint from my side:
Why do you implement MyValue and MyType explcitly in your derived classes? You can just put it into the abstract class, if the implementation is always the same...

Related

Builder Design Pattern C#

there is a concept about inheritance which I do not quite understand.
I have a
protected DeveloperReport DeveloperReport; // Field
Wouldn't PersonalInfoBuilder be able to access that field ?
If yes,
public PersonalInfoBuilder MyPersonalInfo => new PersonalInfoBuilder(DeveloperReport);
Why do I still have to pass the DeveloperReport(field) into PersonalInfoBuilder constructor, when I can
just modify the protected DeveloperReport field by calling new PersonalInfoBuilder(), instead of
new PersonalInfoBuilder(DeveloperReport)?
And, how the concept of "return this" return the changes made to DeveloperReport(field) back to
DeveloperReportBuilder?
Thanks !
class DeveloperReport
{
// Properties
public int Id { get; set; }
public string Name { get; set; }
public DeveloperLevel Level { get; set; }
public int WorkingHours { get; set; }
public int HourlyRate { get; set; }
// Methods
public double CalculateSalary() => WorkingHours * HourlyRate;
}
class DeveloperReportBuilder
{
protected DeveloperReport DeveloperReport;
public PersonalInfoBuilder MyPersonalInfo => new PersonalInfoBuilder(DeveloperReport);
public DeveloperReportBuilder()
{
DeveloperReport = new DeveloperReport();
}
// return developer report.
public DeveloperReport Build() => DeveloperReport;
}
class PersonalInfoBuilder : DeveloperReportBuilder
{
public PersonalInfoBuilder(DeveloperReport report)
{
DeveloperReport = report;
}
public PersonalInfoBuilder()
{
}
public PersonalInfoBuilder NameIs(string name)
{
DeveloperReport.Name = name;
return this;
}
public PersonalInfoBuilder IDis(int id)
{
DeveloperReport.Id = id;
return this;
}
}
You only have to pass the report instance if you want to have both instances of DeveloperReportBuilder and PersonalInfoBuilder have acces to the same instance of DeveloperReport.
Inheritance will not copy the instance values.

Dapper multi mapping set which property is mapped first

I have 2 classes Entity and Instance. Instance class has an Entity object and a list of Attributes like this:
public class Instance
{
public Instance()
{
AttributeList = new ObservableCollection<AttributeClass>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Attributes
{
get => _attributes;
set
{
_attributes = value;
JsonConvert.PopulateObject(Attributes, AttributeList);
}
}
public Entity Entity
{
get => _entity ?? (_entity = new Entity());
set
{
_entity = value;
for (int i = _attributeList.Count - 1; i >= 0; i--)
{
_attributeList.RemoveAt(i);
}
foreach (Entity.AttributesDescribeClass attributeDescribe in _entity.Attributes)
{
_attributeList.Add(new AttributeClass() { AttributesDescribe = attributeDescribe });
}
}
}
public ObservableCollection<AttributeClass> AttributeList
{
get
{
return _attributeList;
}
set
{
_attributeList = value;
_attributes=JsonConvert.SerializeObject(AttributeList);
}
}
public class AttributeClass
{
[JsonIgnore]
public Entity.AttributesDescribeClass AttributesDescribe { get; set; }
public string Name
{
get => AttributesDescribe.Name;
}
public object Value { get; set; }
[JsonIgnore]
public ObservableCollection<InstanceValidator> Validators { get; set; }
public AttributeClass()
{
Validators = new ObservableCollection<InstanceValidator>();
}
}
}
The only this class can work is Entity is always set first, so that it will create the AttributeList, after that, we set Attributes and Populate AttributeList object. But it seems Attributes always set before Entity so this class can't work. Any way to indicate Dapper.NET to set Entity before Attributes?
Dapper processes columns from a reader, left-to-right. So: "whichever field comes back from the database first".

Access const with generics C#

I have the following base class:
public class Base
{
public string LogicalName { get; set; }
public int NumberOfChars { get; set; }
public Base()
{
}
public Base(string logicalName, int numberOfChars)
{
LogicalName = logicalName;
NumberOfChars = numberOfChars;
}
}
and the following derived classes:
public class Derived1 : Base
{
public const string EntityLogicalName = "Name1";
public const int EntityNumberOfChars = 30;
public Derived1() : base(EntityLogicalName, EntityNumberOfChars)
{
}
}
public class Derived2 : Base
{
public const string EntityLogicalName = "Name2";
public const int EntityNumberOfChars = 50;
public Derived2()
: base(EntityLogicalName, EntityNumberOfChars)
{
}
}
and I also have this function that is provided by a service:
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
//Some code to get the entities
}
My problem is how can I call this function generically? I want to call it with something that looks like this:
public void TestEntities<T>() where T : Base
{
var entities = GetEntities<T>(T.EntityLogicalName, T.EntityNumberOfChars);
//some other code to test the entities
}
This of course doesn't work because at this point T is not known. How can I accomplish something similar to this? EntityLogicalName and EntityNumberOfChars are characteristics that all Base derived classes have and they never change for each derived class. Can I get them from the Base class without instantiating objects or some other way that I am not seeing?
Replace constants with getter abstract properties
public abstract class Base
{
public abstract string LogicalName { get; }
public abstract int NumberOfChars { get; }
public Base()
{
}
}
public class Derived1 : Base
{
public string LogicalName { get { return "Name1"; } }
public int NumberOfChars { get { return 30; } }
public Derived1() : base()
{
}
}
Also, you will be able to put some logic into overriden getter, e.g. :
...
public string LogicalName { get { return this.EntityMap.Name; } }
...
UPDATE: The fact that you do not want to instantiate object from class but want to be able to get that string in a strongly typed manner can be handled in one more way. It is totally separate from answer above ( Since you can't override static props in c#). Consider the following code. We are adding one more class here, but LocatorInner can be a member of BaseClass. We are using this approach a lot in several existing apps.:
public class Locator
{
public static class LocatorInner<T> where T : BaseClass
{
public static string Name { get; set; }
}
public static string GetName<T>() where T : BaseClass
{
return LocatorInner<T>.Name;
}
public static void SetName<T>(string name) where T : BaseClass
{
LocatorInner<T>.Name = name;
}
}
public class BaseClass
{
}
public class DerivedClass: BaseClass
{
static DerivedClass()
{
Locator.LocatorInner<DerivedClass>.Name = "me";
}
}
public class TestClass<T> where T : BaseClass
{
public void Method()
{
var name = Locator.GetName<T>();
}
}
IMHO, I believe using constants here is a bad design decision.
You can either solve the issue using #vittore approach, but for me it sounds like you should use meta-programming with attributes if you're looking to get data from the T generic argument
For example, what about:
public class LogicalNameAttribute : Attribute
{
public LogicalNameAttribute(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class NumberOfCharsAttribute : Attribute
{
public NumberOfCharsAttribute (int number)
{
Number = number;
}
public string Number { get; private set; }
}
[LogicalName("Name1"), NumberOfChars(30)]
public class Derived1 : Base
{
public Derived1() : base()
{
}
}
Now your service method can extract attribute metadata as follows:
public void TestEntities<T>() where T : Base
{
LogicalNameAttribute logicalNameAttr = typeof(T).GetCustomAttribute<LogicalNameAttribute>();
NumberOfCharsAttribute numberOfCharsAttr = typeof(T).GetCustomAttribute<NumberOfCharsAttribute >();
Contract.Assert(logicalNameAttr != null);
Contract.Assert(numberOfCharsAttr != null);
string logicalName = logicalNameAttr.Name;
int numberOfChars = numberOfCharsAttr.Number;
// Other stuff
}
There's a performance penalty because you need to use reflection to get attributes applied to T, but you gain the flexibility of not forcing derived classes to provide this static info.
As #vittore mentioned, move the properties to base,pass the hard coded values from derived and in creation use just defautl(T)
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
yield return default(T); //Is its always class use new constraint and return new T();
}

C# Inheritance, new modifier and generics

I'm having a hard trying to find to correct approach to this :
My data structures :
public abstract class Flow
{
public virtual double Value { get; set; }
public virtual DateTime Time { get; set; }
}
public class InboundFlow : Flow
{
}
public class OutboundFlow : Flow
{
}
My business objects containing collections of these data structures
public abstract class Fluent
{
public virtual IList<Flow> FlowCollection { get; set; }
public virtual double InitialBaseflow { get; set; }
}
public class Affluent : Fluent
{
public new virtual IList<InboundFlow> FlowCollection { get; set; }
}
public class Effluent : Fluent
{
public new virtual IList<OutboundFlow> FlowCollection { get; set; }
}
The generic method I'm trying to use :
private static void FindInitialBaseflow<T>(ref T fluent) where T : Fluent
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.ToList().FindAll(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
My problem is that calling "linqfluent.FlowCollection" in the linq method calls for the base class Fluent's FlowCollection, which is null.
How can I force the use of the child's property instead? Thanks!
You need to make the collection within Fluent generic so that the classes that inherit from it can specify the type:
public class Fluent<T>
where T : Flow
{
public IList<T> FlowCollection { get; set; }
public double InitialBaseflow { get; set; }
}
Once you have that you don't even need sub classes of Flow, you can just make it concrete.
Your use of it would be easily modified to fit this model:
private static void FindInitialBaseflow<T>(Fluent<T> fluent)
where T : Flow
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.Where(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
Also note that since you're not setting fluent in this method, there is no need to pass it by reference. It's already a class, so it is itself a reference; mutations of the referenced object will be observed by the caller.
Generics are the wrong tool. You should using polymorphism to ensure the correct implementation is called based on the type.
For example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApp
{
public abstract class Flow
{
public virtual double Value { get { return new Random().Next() ; } }//these values are just for demonstration purposes
public virtual DateTime Time
{
get
{
return DateTime.MinValue.AddYears(1);
}
}
}
public class InboundFlow : Flow
{
}
public class OutboundFlow : Flow
{
}
public abstract class Fluent
{
IList<Flow> _flowCollection;
public virtual IList<Flow> FlowCollection
{
get { return _flowCollection; }
set { _flowCollection = value; }
}
private double _initialBaseflow;
public virtual double InitialBaseflow
{
get { return _initialBaseflow; }
set { _initialBaseflow = value; }
}
public Fluent()
{
FlowCollection = new List<Flow>();
}
}
public class Affluent : Fluent
{
//public new virtual IList<InboundFlow> FlowCollection { get; set; }//Keep the property polymorphic
public Affluent()
{
FlowCollection = new List<Flow>();
}
}
public class Effluent : Fluent
{
//public new virtual IList<OutboundFlow> FlowCollection { get; set; }
public Effluent()
{
FlowCollection = new List<Flow>();
}
}
class Program
{
public static DateTime SOME_DATE { get { return DateTime.MinValue; } }
public static DateTime SOME_OTHER_DATE { get { return DateTime.Now; } }
static void Main(string[] args)
{
var inbound = new InboundFlow();
var inbound2 = new InboundFlow();
var outbound = new OutboundFlow();
var a = new Affluent();
a.FlowCollection.Add(inbound);
a.FlowCollection.Add(inbound2);
FindInitialBaseflow(a);
}
private static void FindInitialBaseflow(Fluent fluent)
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.ToList().FindAll(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
}
}

Get properties from derived class in base class

How do I get properties from derived class in base class?
Base class:
public abstract class BaseModel {
protected static readonly Dictionary<string, Func<BaseModel, object>>
_propertyGetters = typeof(BaseModel).GetProperties().Where(p => _getValidations(p).Length != 0).ToDictionary(p => p.Name, p => _getValueGetter(p));
}
Derived classes:
public class ServerItem : BaseModel, IDataErrorInfo {
[Required(ErrorMessage = "Field name is required.")]
public string Name { get; set; }
}
public class OtherServerItem : BaseModel, IDataErrorInfo {
[Required(ErrorMessage = "Field name is required.")]
public string OtherName { get; set; }
[Required(ErrorMessage = "Field SomethingThatIsOnlyHereis required.")]
public string SomethingThatIsOnlyHere{ get; set; }
}
In this example - can I get the "Name" property from ServerItem class while in BaseModel class?
EDIT:
I'm trying to implement model validation, as described here:
http://weblogs.asp.net/marianor/archive/2009/04/17/wpf-validation-with-attributes-and-idataerrorinfo-interface-in-mvvm.aspx
I figured that if I create some base model with (almost) all of the validation magic in it, and then extend that model, it will be okay...
If both classes are in the same assembly, you can try this:
Assembly
.GetAssembly(typeof(BaseClass))
.GetTypes()
.Where(t => t.IsSubclassOf(typeof(BaseClass))
.SelectMany(t => t.GetProperties());
This will give you all the properties of all the subclasses of BaseClass.
If you require that a derived class must implement a method or property, you should introduce that method or property into the base class as an abstract declaration.
For example, for your Name property, you would add to the base class:
public abstract string Name { get; set; }
Then any derived classes must implement it, or be abstract classes themselves.
Once you have added the abstract version of the Name property to the base class, you will be able to access it in the base class anywhere except in the base class's constructor.
If you must do literally fetch property of derived class from within base class, you can use Reflection, for example - like this...
using System;
public class BaseModel
{
public string getName()
{
return (string) this.GetType().GetProperty("Name").GetValue(this, null);
}
}
public class SubModel : BaseModel
{
public string Name { get; set; }
}
namespace Test
{
class Program
{
static void Main(string[] args)
{
SubModel b = new SubModel();
b.Name = "hello";
System.Console.Out.WriteLine(b.getName()); //prints hello
}
}
}
This is not recommended, though, and you most probably should rethink your design like Matthew said.
As for not throwing properties to your base classes -- you can try to decouple base and deriving classes into unrelated objects and pass them via constructors.
Another way to solve this issue by create virtual property in base class and override it to derived class.
public class Employee
{
public virtual string Name {get; set;}
}
public class GeneralStaff
{
public override string Name {get; set;}
}
class Program
{
static void Main(string[] args)
{
Employee emp = new GeneralStaff();
emp.Name = "Abc Xyz";
//---- More code follows----
}
}
Okay, I solved this problem slightly different than the author of this post: http://weblogs.asp.net/marianor/archive/2009/04/17/wpf-validation-with-attributes-and-idataerrorinfo-interface-in-mvvm.aspx
public abstract class BaseModel : IDataErrorInfo {
protected Type _type;
protected readonly Dictionary<string, ValidationAttribute[]> _validators;
protected readonly Dictionary<string, PropertyInfo> _properties;
public BaseModel() {
_type = this.GetType();
_properties = _type.GetProperties().ToDictionary(p => p.Name, p => p);
_validators = _properties.Where(p => _getValidations(p.Value).Length != 0).ToDictionary(p => p.Value.Name, p => _getValidations(p.Value));
}
protected ValidationAttribute[] _getValidations(PropertyInfo property) {
return (ValidationAttribute[])property.GetCustomAttributes(typeof(ValidationAttribute), true);
}
public string this[string columnName] {
get {
if (_properties.ContainsKey(columnName)) {
var value = _properties[columnName].GetValue(this, null);
var errors = _validators[columnName].Where(v => !v.IsValid(value)).Select(v => v.ErrorMessage).ToArray();
return string.Join(Environment.NewLine, errors);
}
return string.Empty;
}
}
public string Error {
get { throw new NotImplementedException(); }
}
}
Maybe it will help somebody.
Scan your assembly for all inherited classes from BaseModel and create dictionary like this:
Dictionary<Type, Dictionary<string, Func<BaseModel, object>>>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TESTNEW
{
public abstract class BusinessStructure
{
public BusinessStructure()
{ }
public string Name { get; set; }
public string[] PropertyNames{
get
{
System.Reflection.PropertyInfo[] Pr;
System.Type _type = this.GetType();
Pr = _type.GetProperties();
string[] ReturnValue = new string[Pr.Length];
for (int a = 0; a <= Pr.Length - 1; a++)
{
ReturnValue[a] = Pr[a].Name;
}
return ReturnValue;
}
}
}
public class MyCLS : BusinessStructure
{
public MyCLS() { }
public int ID { get; set; }
public string Value { get; set; }
}
public class Test
{
void Test()
{
MyCLS Cls = new MyCLS();
string[] s = Cls.PropertyNames;
for (int a = 0; a <= s.Length - 1; a++)
{
System.Windows.Forms.MessageBox.Show(s[a].ToString());
}
}
}
}

Categories