EF6 - BaseClass data duplication - c#

I have a base class A and derived class B. B is introduced in my latest migration. I am going for a Table-per-Type inheritance. There can be many Bs for one A. The error I am getting when trying to update-database is related the Index on A.Designation, because the DB gets populated by the Seed method. I do understand where this error comes from, but I do not know how to avoid it.
The base class:
[Table("As")]
class A
{
[Key]
public Id { get; set; }
[Index(IsUnique = true)]
public string Designation { get; set; }
// This is mapped via EF and required by Bs constructor
public ICollection<SomeType> SomeType { get; set; }
// Parameter less constructor for EntityFramework
private A() { }
public A(string designation)
{
Designation = designation;
}
}
The derived class:
[Table("Bs")]
class B : A
{
public B(A a) : base(a.designation)
{
foreach (SomeType someType in A.SomeTypes)
{
// Do something
}
}
}
So in the Seed method first an instance a of A, then an instance b of B based on a is added to the DB.
As I understand it, calling new B(a) creates a new instance of A which also is added to the DB which fails because of the unique index.
How do I avoid this?
I want the data to be referenced, not duplicated. I guess it would be possible to use a Table-per-Hierarchy scheme but that would duplicate the data of A for each B, (right?) which I would like to avoid, especially because A.SomeEntities would have its entries duplicated as well.
Another possibility that just popped into my mind, is passing the the Id of a to b's constructor, but that would then have to call the DbContext and probably imply some other weirdness I am missing right now.

Looks like you are trying to link with existing object instead of class inheritance?
Why not create a link between your b and a?
[Table("Bs")]
class B
{
public A referredA {get;set;}
public B(A a)
{
referredA=a;
}
}

Related

What is the best way to handle multiple (potentially null) navigation properties?

I have 3 classes
public class ActivityLog
{
// The activity log affects an employee
public int EmployeeID { get; set; }
public Employee Employee { get; set; }
// The activity log affects a department
public int DepartmentID { get; set; }
public Department Department { get; set; }
}
In this example there are two different object types that could be displayed on the view, but in reality there are much more types that differ and for which it doesn't seem sensible to move it to its own inheritance model.
I would like to be able to do the below:
public class ActivityLog<T>
{
// The activity log affects an unknown type
public T ConcernedObjectID { get; set; }
public T ConcernedObject { get; set; }
}
Right now we have a lot of null checks in our view (if employee is null then use department).
Is this something that entity framework can help with somehow, or would it be best to implement a code only solution (e.g. Interfaces)?
I think you have a design problem here. The ActivityLog class tries to do too much. Its both an entry in the log for an employee and for a department. Which are completely different things. The only thing they have in common is that they can be put into an activity log.
I would either use a common interface or an abstract base class. You can then use the asp.net equivalent of data templates to visualize the data.
So something like this:
public abstract class ActivityLogEntry
{
int Id { get; }
}
public EmployeeActivityLogEntry : ActivityLogEntry
{
Employee Employee {get;}
}
public DepartmentActivityLogEntry : ActivityLogEntry
{
Department Department {get;}
}
Another thing that can help you with null checks is to make it explicit that something can be null. I use the Optional NuGet package for that. This gives you something like this
Option<Employee> Employee {get; }
public string ToString()
{
return this.Employee.Match(e => e.Name, () => "");
}
In this case you cannot directly access the Employee that is captured in the Option. Instead you have to provide a Func for what to do when there is an Employee (its not null) and for when there isn't. There are a lot more helper functions in the optional library. It makes it a lot clearer that you need to handle both cases. You can no longer be surprised by something begin null.
(Of course you should not use Option<T> for everything. Only use it on properties that can sometimes be null. Not on properties that should never be null, or you start hiding bugs from yourself).

Initialise one object from another where they share a common interface c#

I want to pass in an instance of an interface to an object and initialise all the values of this object to those of the object passed in where both objects implement the same interface? Are there any good shortcuts in this particular case where they share an interface. It seems to me there must be... I just can't recall ...
EDIT: After John's feedback, the question is better expressed as - How do I pass in an instance of an interface to an object's constructor and initialise all the values of this object to those of the interface instance passed in?
Most deep copying solutions (including my own previous solutions) return an object - which is not going to work in a constructor, or rely upon creating a new instance (which is not going to work with an interface as the source and destination).
I want to pass in both source and destination and have properties of the source copied to the destination where they are both interfaces. Is there an existing solution for this. Or do I revisit my own code and try to adapt it - my previous own solution from 2009 (with minor bug corrected in the answers) SetValue on PropertyInfo instance error "Object does not match target type" c# AND svics answer in transfering one object properties values to another one suffice for the simple cases where all properties are just values.
e.g.
public interface ISomething
{
...
}
public class A : ISomething
{
public A(ISomething input)
{
// what goes here??
}
}
I'm not really sure I fully understand your restrictions, but for most object copying work I use AutoMapper, which greatly helps with the grunt work of copying objects. It means a different approach than copying properties in constructors, but maybe useful. Here's some example code:
public interface ISomething {
string MyProperty { get; set; }
int AnotherProperty { get; set; }
B ClassProperty { get; set; }
}
public class A : ISomething {
public string MyProperty { get; set; }
public int AnotherProperty { get; set; }
public B ClassProperty { get; set; }
}
public class B {
public string BProperty_1 { get; set; }
public int BProperty_2 { get; set; }
}
class Program {
static void Main(string[] args) {
// Configure the mapping
Mapper.Initialize(cfg => cfg.CreateMap<ISomething, ISomething>());
// Initialize first instance
var firstA = new A {
MyProperty = "Test",
AnotherProperty = 21,
ClassProperty = new B {
BProperty_1 = "B String",
BProperty_2 = 555
}
};
// Initialize second instance and perform the mapping
var secondA = Mapper.Map<ISomething>(firstA);
Here, all the properties in firstA are copied over to secondA, including the properties in ClassProperty.
The mapping configuration is performed once on startup, and uses recursion and reflection to build the mapping model. It can then be used anywhere in your code. If new properties are added to the interface, the mapping configuration stays the same.
Simply set all the properties of the interface in the constructor:
public class A : ISomething
{
public A(ISomething input)
{
A.MyProperty = input.MyProperty;
A.AnotherProperty = somethingNotFromTheInterface
}
}
This is called a copy-constructor. Wheather this actually creates a deep or a shallow copy of your existing instance depends on if it contains references to other reference-types. In this case you´d have to re-create all those instances also:
public A(ISomething input)
{
A.MyProperty = new MyType(input.MyProperty);
A.AnotherProperty = somethingNotFromTheInterface
}
Which itself assumes you hacve a copy-constructor for the type of MyProperty also.
This can become some huge task when your interface is quite big. You may consider looping all the interfaces properties with reflection in this case, or even better rethink if your interface is actually serving a single purpose and not doing too much.

inheritance of abstract class with static property in C#

Short version:
I have an abstract class A. It has a method that needs to know the value of a static class property that is specific to each subclass. The name and type is the same, just the value can be unique for each subclass.
Can I define this static property in the base class A to be able to access it with methods defined in A, but keeping the property's values of different subclasses unrelated?
Or how would I implement something like that?
Long version:
Let's say I have an abstract base class for data models. It has a public property Id (Int32).
I would like to implement a constructor in the base class that generates a new ID based on the last assigned ID for objects of a subclass.
The reason is that the real IDs are assigned automatically by the database, but each data model object already has to have a unique ID when it gets constructed without being written to the database yet. As the database assigns only positive integers as ID, my plan is to assign newly created data model objects a temporary, unique negative ID. As soon as the object gets written, the ID will get changed to the real one.
As I have quite a few different data model classes all deriving from my abstract base class, I thought it would be good to include that functionality there to not duplicate it. But each subclass has to have their own counter that points to the next free negative ID, as the different classes' IDs are unrelated.
So I need a static property in each subclass storing this class' last assigned temporary ID, but the mechanism to assign it is always the same and could be implemented into the abstract base class' constructor. However, I can't access a property from the base class that has to be implemented by the subclasses, which means I have to define it in the base class. But will this static property then be global for all subclasses, which is not what I want?
How can I implement this temporary ID counter the most elegant way?
Simplified code example:
public abstract class ModelBase
{
public Int32 Id { get; set; }
protected static Int32 LastTempId { get; set; } = 0;
public ModelBase()
{
Id = --LastTempId;
}
}
public class Model1 : ModelBase
{
public Model1 () : base ()
{
// do something model1-specific
}
}
public class Model2 : ModelBase
{
public Model2() : base()
{
// do something model2-specific
}
}
If I implement it like this, I fear that for both subclasses model1 and model2, the inherited static property LastTempId will be the same instance. But I want a separate counter for each subclass while still using it in the base class constructor.
Short answer
The sub-classes cannot have different values for the static property because the static property is a property of the class, not of it's instances, and it's not inherited.
Long answer
You could implement a single counter on the abstract class as a static property and have one constructor of the abstract class using it.
EDIT: To save different counters for each sub-class you could use a static dictionary mapping a Type (sub-class) to a counter.
public abstract class A<T>
{
public static Dictionary<Type, int> TempIDs = new Dictionary<Type, int>();
public int ID { get; set; }
public A()
{
if (!TempIDs.ContainsKey(typeof(T)))
TempIDs.Add(typeof(T), 0);
this.ID = TempIDs[typeof(T)] - 1;
TempIDs[typeof(T)]--;
}
}
public class B : A<B>
{
public string Foo { get; set; }
public B(string foo)
: base()
{
this.Foo = foo;
}
}
public class C : A<C>
{
public string Bar { get; set; }
public C(string bar)
: base()
{
this.Bar = bar;
}
}
B b1 = new B("foo");
B b2 = new B("bar");
C c1 = new C("foo");
C c2 = new C("foo");
b1.ID would be -1, b2.ID would be -2, c1.ID would be -1 and c2.ID would be -2
First of all, my humble opinion is entities shouldn't be responsible of assigning their own unique identifier. Keep a clear separation of concerns.
There should be another player in that game that should assign those temporary unique identifiers (either if they're negative or positive integers).
Usually, that so-called other player is an implementation of repository design pattern which is responsible of translating the domain (your models) into the definitive representation of your data and vice versa.
Usually a repository has a method to add objects. And this should be the point where you set these temporary identifiers:
public void Add(Some some)
{
some.Id = [call method here to set the whole id];
}
And, most repository implementations are per entity.
CustomerRepository
InvoiceRepository
...
...but this doesn't prevent you from defining a base repository class which could implement what can be in common when handling some entity types:
public interface IRepository<TEntity> where TEntity : EntityBase
{
// Other repository methods should be defined here
// but I just define Add for the convenience of this
// Q&A
void Add(TEntity entity);
}
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : EntityBase
{
public virtual void Add(TEntity entity)
{
entity.Id = [call method here to set the whole id];
}
}
...and now any class deriving Repository<TEntity> will be able to generate a temporary identifier for their specialized entities:
public class CustomerRepository : Repository<Customer> { }
public class InvoiceRepository : Repository<Invoice> { }
How you could implement the unique and temporary entity identifier as part of the abstract repository class and being able to do so for each specific entity type?
Use a dictionary to store per-entity last assigned identifier implementing a property to Repository<TEntity>:
public Dictionary<Type, int> EntityIdentifiers { get; } = new Dictionary<Type, int>();
...and a method to decrease next temporary identifier:
private static readonly object _syncLock = new object();
protected virtual void GetNextId()
{
int nextId;
// With thread-safety to avoid unwanted scenarios.
lock(_syncLock)
{
// Try to get last entity type id. Maybe the id doesn't exist
// and out parameter will set default Int32 value (i.e. 0).
bool init = EntityIdentifiers.TryGetValue(typeof(TEntity), out nextId);
// Now decrease once nextId and set it to EntityIdentifiers
nextId--;
if(!init)
EntityIdentifiers[typeof(TEntity)] = nextId;
else
EntityIdentifiers.Add(typeof(TEntity), nextId);
}
return nextId;
}
Finally, your Add method could look as follows:
public virtual void Add(TEntity entity)
{
entity.Id = GetNextId();
}
One way to go is reflection, but it takes run-time and is prone to runtime errors. As others mentioned: you cannot force inheriting classes to redeclare some static field and be able to use this field in ancestor class. So I think minimal code redundancy is necessary: each inheriting class should provide it's own key generator. This generator can be kept in static field of the class of course.
(Note this is not necessarily thread-safe.)
class KeyGenerator
{
private int _value = 0;
public int NextId()
{
return --this._value;
}
}
abstract class ModelBase
{
private KeyGenerator _generator;
public ModelBase(KeyGenerator _generator)
{
this._generator = _generator;
}
public void SaveObject()
{
int id = this._generator.NextId();
Console.WriteLine("Saving " + id.ToString());
}
}
class Car : ModelBase
{
private static KeyGenerator carKeyGenerator = new KeyGenerator();
public Car()
: base(carKeyGenerator)
{
}
}
class Food : ModelBase
{
private static KeyGenerator foodKeyGenerator = new KeyGenerator();
public Food()
: base(foodKeyGenerator)
{
}
}
class Program
{
static void Main(string[] args)
{
Food food1 = new Food();
Food food2 = new Food();
Car car1 = new Car();
food1.SaveObject();
food2.SaveObject();
car1.SaveObject();
}
}
This produces:
Saving -1
Saving -2
Saving -1
Just generate a GUID for each object before it gets added to your database. You could have an isAdded flag that tells you the object should be referred to be GUID, or clear the GUID once the object is added. With a GUID you never have to worry that two objects will clash. Also it obviates the need for separate IDs per subclass. I would not reuse the same property for two states as you propose.
https://msdn.microsoft.com/en-us/library/system.guid(v=vs.110).aspx
Well, static classes aren't inherited, so that's out,m and you can't force subclasses to implement a static method, so that's out too.
Rather than putting that method in the class itself, why not have a base interface that you can implement. Then you can have an instance method that can be abstract:
public interface IDataModelFactory<T> where T:ModelBase
{
int GetLastTempId();
}
public Model1Factory : IDataModelFactory<Model1>
{
public int GetLastTempId()
{
// logic for Model1
}
}
public Model2Factory : IDataModelFactory<Model2>
{
public int GetLastTempId()
{
// logic for Model2
}
}
Or if the logic is common to all classes, have an abstract base class with (or without) the interface:
public DataModelFactory<T> : IDataModelFactory<T>
{
public virtual int GetLastTempId()
{
// common logic
}
// other common logic
}
You could even make the factories singletons so you don't have to create instances all the time, and they can even be sub-classes of the model classes so they're closely linked.
As a side note, if you're uncertain what the inheritance/interface relationship would be, I often find it's quicker start with copy/paste reuse and refactor your code to introduce base classes and interfaces. That way you know what the common code is and can refactor that into common methods. Otherwise you are tempted to try and put everything in the base class and use switches or other constructs to change logic based on the derived type.

C# looking for a pointer workaround

I'm trying to create a foreign key in a class, B, to the id of another class, A. The problem is that I can't verify the ID of A's objects until near the end of the program when all my instances of B have already been created. I would like to be able to instantiate objects of B with a reference to the id of an A object so that when the id of the A object changes, so does the value of the foreign key in B. I know I can't do that directly in C# without using 'unsafe' mode so I've been looking for alternative methods. As a last resort I could do a loop at the end through all my B objects, but B is actually many different classes and objects and there are enough of them that I would much prefer a more efficient solution.
Here's a rough example of the logic that I need.
using System;
namespace sandbox
{
public class A
{
public int ID;
public A(int id)
{
ID = id;
}
}
public class B
{
public int reftoAID;
public B(int id)
{
reftoAID = id;
}
}
public class TestMain
{
static void Main()
{
A a = new A(1);
B b = new B(a.ID);
a.ID = 3;
Console.WriteLine(b.reftoAID); //prints 1, but I need 3
Console.ReadLine();
}
}
}
I have tried creating a wrapper class with an int property that holds the id, but I haven't been able to figure out how to get it into the database using linqtodb. I thought I would be able to just define an (int) cast, but that doesn't work. From what I can tell, linqtodb uses the System.Data.DbType enum to determine the type and I don't know if there's a way to have it convert before the lookup.
I'm looking either for a new approach to the problem or a way of converting the wrapper class in such a way that it can be written to the database.
C# doesn't use pointers for referencing objects. Instead, C# has the concept of value types and reference types. All classes are reference types, which means that a variable of that type is a reference to an object. This is very similar to pointers in other programming languages.
Using direct references, your code would look like this (some name changes for clarity):
public class ClassA
{
public int ID;
public ClassA(int id)
{
ID = id;
}
}
public class ClassB
{
public ClassA A;
public ClassB(ClassA a)
{
A = a;
}
}
public class TestMain
{
static void Main(string[] args)
{
ClassA a = new ClassA(1);
ClassB b = new ClassB(a);
a.ID = 3;
Console.WriteLine(b.A.ID); //prints 3
Console.ReadLine();
}
}
The constructor for ClassB takes a reference to an object of type ClassA, so any changes to that object are reflected when it is accessed through the A property of ClassB.
I was able to solve this using properties, which I had completely forgotten about when I asked this question initially. Using BJ Myers' example:
public class ClassB
{
ClassA A;
public int AID { get {return A.ID;} }
public ClassB(ClassA a)
{
A = a;
}
}

Fluent NHibernate - Query over a derived class

Lets say I have two classes:
public class A
{
public virtual int Id { get; set; }
public virtual Object1 Obj { get; set; }
}
public class B : A
{
public new virtual Object2 Obj { get; set; }
}
I use Fluent NHibernate and I have created two different mappings for the two classes. However, when I try to query class A in my repository, FNH finds both class B and A, which kind of makes sense since both are A.
Example (this criteria will query over both A and B):
public List<T> GetByName(string name)
{
return Session.CreateCriteriaOf<A>.Add(Restrictions...);
}
When writing CreateCriteriaOf<A>, I only want to query over A - not B. How can I solve my problem?
I think you better make an inheritance tree where both A and B derive from a common (abstract) base type. Then NHibernate can make the distinction by a discriminator column.
Of course, your data model should accommodate this, so I hope your model is not prescribed in any way.

Categories