EF: Many tables with the same column - can I access to it without copying the code? - entity-framework

I have some tables which stores the file's data, e.g TabA, TabB, TabC, ... TabX. Each of them has the same column FileTypeID.
For each table I need to use the extension method to get the rows depending of the condition of the FileTypeID column. To do so, I have an extension method like that:
public static class FilesTab_Extenders
{
public static IList<TabA> GetSpecificFiles(this EntityCollection<TabA> mc)
{
///
}
}
but, I don't want mindlessly clone the same code for the rest of tables. The only difference will be the parameter - this EntityCollection<TabB>, this EntityCollection<TabC> etc. So, is it somehow possible to make the universal code for that scenario ?

To me the easiest way to do this would be to use an interface. You would then have your partial classes implement this interface and use it in your extention method:
public interface IFileTypeable
{
Guid FileTypeId { get; set;}
}
Now you would create partial class files for each of your TabA, TabB, TabC, ... TabX that follow this template:
namespace MyDBContextNamespace
{
public partial class TabA : IFileTypeable
{
// no need to do anything, the property is already implemented on the original class file.
}
public partial class TabB : IFileTypeable
{
// no need to do anything, the property is already implemented on the original class file.
}
}
Finally your extention method would be changed to look like this:
public static IList<IFileTypeable> GetSpecificFiles(this EntityCollection<IFileTypeable> mc)
{
foreach (var item in mc)
{
Guid fileTypeId = item.FileTypeId;
}
}

Related

how to change auto generated "shadow properties" foreign key name for all entities?

i've a model like that
public class Class1 {
public int identifier {get;set;}
}
public class Class2 {
public int identifier {get;set;}
public List<Class1> holders {get;set;}
public List<Class1> users{get;set;}
}
my problem is the generated foreign keys in Class1 name are "Class2_identifier" and "Class2_identifier1" mean while what i want is "Class2_holders_identifier" and "Class2_users_identifier"
the real model is really huge so what i'm looking for is away to override how the names are generated in the "add-migration" step
Not a complete implementation, just a hint: If you are using EntityFramework 6 you can define a custom model convention:
public class ForeignKeyNamingConvention : IStoreModelConvention<AssociationType>
{
public void Apply(AssociationType association, DbModel model)
{
if (association.IsForeignKey)
{
var constraint = association.Constraint;
// Implement your renaming code.
// The data you need is inside association.Constraint.
}
}
}
And add it to your DbContext.OnModelCreating:
modelBuilder.Conventions.Add(new ForeignKeyNamingConvention());
This answer contains some code that you can reuse (in this case the convention is used to remove underscores in the column names).
Edit: OP included their final solution here:
The problem as mentioned in ef core "it's the same problem in ef6 but with no message" console
There are multiple relationships between 'Class1' and 'Class2' without configured foreign key properties causing EF to create shadow properties on 'Organization' with names dependent on the discovery order.
public class ForeignKeyNamingConvention : IStoreModelConvention<AssociationType>
{
public void Apply(AssociationType association, DbModel model)
{
if (association.IsForeignKey)
{
var constraint = association.Constraint;
// as i just needed the fk column name to be more clear
// "{entityName}_{propertyName}" which is provided in
// {association.Name}
association.Constraint.ToProperties[0].Name = association.Name;
}
}
}

Autofac registering all subtypes keyed according to a property

The following scenario:
public enum ChildType
{
Type1,
Type2,
Type3
}
public abstract class MyParentClass
{
public abstract ChildType Id { get; }
}
public class Child1 : MyParentClass
{
public override ChildType Id { get { return ChildType.Type1; } }
}
public class Child2 : MyParentClass
{
public override ChildType Id { get { return ChildType.Type2; } }
}
public class Child3 : MyParentClass
{
public override ChildType Id { get { return ChildType.Type3; } }
}
and i would like to use autofac to register all the subtypes using their id as a key, so something like:
builder.RegisterAssemblyTypes(ThisAssembly)
.Where(type => type.IsSubclassOf(typeof(MyParentClass)))
.Keyed<MyParentClass>(c => c.Id)
.SingleInstance();
now obviously the above doesn't work, but is there some way to achieve that without registering each subclass separately? I want to then be able to access them by the enum, i.e. at runtime when i don't know what the value of the enum will be:
public static MyParentClass GetSubClassByEnum(ChildType id)
{
AutofacHostFactory.Container.ResolveKeyed<MyParentClass>(id);
}
Unfortunately you probably won't be able to get exactly this setup working because it's sort of a chicken/egg problem - you want to resolve an object based on information that won't be available... unless you resolve the object.
One way to get this working is to use attributes rather than properties. Attributes are available before the type is instantiated so you could store the info there and achieve the desired result.
Autofac has attribute metadata support that allows you to create custom attributes to provide this sort of information. You could create an attribute that gets inherited and only allows one instance per class. Apply it with the default value to your base class, then when you need to override apply a new attribute on the derived class.
There is plenty of documentation with examples on the Autofac doc site showing how to work with this.

Entity Framework code first Inheritance Issue

I have code first implementation for flowing hierarchy,
BaseContact{
Public int Id{get;set;}
public string Name{get;set;}
//..
}
Person:BaseContact{
public string Designation{get;set;}
//..
}
Company:BaseContact{
public int NumOfEmployees{get;set;}
//..
}
I want to identify person or company with by using only the Id value? Currently I am using reflection to identify whether it is a person or company. Is there any other way to identify it without doing too much?
Without seeing how you initialised your classes I'm going to assume you have a table per concrete type approach.
You can't do it just from the ID, as you don't know which table the ID belongs to. ID 2 in "Person" table is a different entity to ID 3 in "Company". The only practical way to identify only from an ID is using a Table per Hierarchy approach and inspecting the type descriptor.
Some good references
http://weblogs.asp.net/manavi/archive/2011/01/03/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines.aspx
http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx
You can also use a simple is statement instead of reflection. Ie if (entity is Company)
In your BaseContact (assume it is an abstract class) add abstract property which will be implemented by other two classes.Use Enum to identify the property type as follows.
public enum MyType
{
Person,
Company,
};
public abstract class BaseContact{
public abstract MyType ContactType{get;}
}
public class Person:BaseContact
{
public override MyType ContactType
{
get
{
return MyType.Person;
}
}
}
public class Company:BaseContact
{
public override MyType ContactType
{
get
{
return MyType.Company;
}
}
}
Use your BaseContact repository to retrieve entities and use enum for type separation.

Persist derived objects using Mongo C# driver

I have the following class hierarchy
[BsonKnownTypes(typeof(MoveCommand))]
public abstract class Command : ICommand
{
public abstract string Name
{
get;
}
public abstract ICommandResult Execute();
}
public class MoveCommand : Command
{
public MoveCommand()
{
this.Id = ObjectId.GenerateNewId().ToString();
}
[BsonId]
public string Id { get; set; }
public override string Name
{
get { return "Move Command"; }
}
public override ICommandResult Execute()
{
return new CommandResult { Status = ExecutionStatus.InProgress };
}
}
if I save the command like so:
Command c = new MoveCommand();
MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c);
and then query the DB, I don't see the derived properties persisted.
{ "_id" : "4df43312c4c2ac12a8f987e4", "_t" : "MoveCommand" }
I would expect a Name property as a key in the document.
What am I doing wrong?
Also, is there a way to avoid having a BsonKnowTypes attribute on the base class for persisting derived instances? I don't see the why a base class needs to know about derived classes. This is bad OO design and is being forced on my class hierarchy by the BSON library. Am I missing something here?
1.Name property was not saved into database because it haven't setter. Serializers not serialize properties that's haven't setters (because if serializer serialize such property it will not able deserialize it back). So if you want serialize Name property then just add fake setter(into ICommand need to add it also):
public override string Name
{
get { return "Move Command"; }
set{}
}
2.If you don't want use BsonKnownTypes attribute there is another way to notify serializer about know types it might encounter during deserialization. Just Register maps once, on app start event:
BsonClassMap.RegisterClassMap<MoveCommand>();
//all other inherited from ICommand classes need register here also
So you should use or KnownTypes attribute or register BsonClassMap for each polymorphic class, otherwise you will get 'unknown descriminator' error during deserializtion:
var commands = col.FindAllAs<ICommand>().ToList();
3 You said:
This is bad OO design and is being
forced on my class hierarchy by the
BSON library.
In any way even without KnownTypes atribute your code using Bson lib through BsonId attribute.
If you want avoid it you can:
BsonClassMap.RegisterClassMap<MoveCommand>(cm => {
cm.AutoMap();
cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});
So now you can remove reference to Mongodb.Bson lib from your domain code lib.

Does MEF Support Customized CTOR?

It looks like that MEF framework creates objects which have default CTOR. How about customized CTOR, or Constructor with parameters? For example:
[Export (typeof(IInterface1))]
public class MyClass : IInterface1
{
public MyClass(int id) {....}
....
}
If not, one way I can think is to pass object as parameters to CTOR. For example:
public Interface IParameterID {
public int Id { get; private set; }
...
}
Then the CTOR will be:
public MyClass([Import(typeof(IParameter))] IParameterID id)
{ ... }
Not sure if it is possible to add attribute to CTOR's parameters? And the next question is that if MEF will automatically create an instance of IParameter and inject it to the CTOR's parameter?
Yes, this is possible. Just put an [ImportingConstructorAttribute] on the constructor you would like to use. The parameters will automatically be treated as imports, but if you need to change the contract name on them you can also put an import attribute on them.