locked
Entity Framework: nullable keys and interfaces RRS feed

  • Question

  • Hi,

      I want to develop my corporation framework using entity framework 4.0.
    Entities in this framework must follow these rules:

    - All properties must be nullable

    - Each entity must have 2 interfaces, one interface contains all fields and the other one contains navigations

    - Each entity has hierachical inheritance, some entities in this hierarchy could save in related tables
     
    In addition, i want to be able to use features like Entity splitting mapping scenario (http://msdn.microsoft.com/en-us/library/cc716779.aspx). Also maybe i need to create my entities run-time in future, so i don't want to be restricted by deginers.

    i.e. for customer can make many orders, so customer table and entities are like these:

    Table: TBL_Customer

    Id,       int,          not null,   primary key
    FullName, varchar(100), allow nulls

    Table: TBL_Order

    Id,         int,      not nulls,   primary key
    OrderDate,  datetime, allow nulls, 
    CustomerId, int,      allow nulls

    Relation: TBL_Customer.Id <- 1..* -> TBL_Order.CustomerId

    in CommonEntities.dll :

    interface IModelBase
    {
    int? Id {get;set;}
    }

    class ModelBase : IModelBase
    {
    int? Id {get;set;}
    }

    in PartyEntities.dll :

    interface ICustomerData : IModelBase
    {
    string FullName {get;set;}
    }

    class CustomerData : ModelBase, ICustomerData
    {
    string FullName {get;set;}
    }

    interface ICustomerEntity : ICustomerData
    {
    IList<IOrderEntity> theOrders {get;set;}
    }

    class CustomerEntity : CustomerData, ICustomerEntity
    {
    IList<IOrderEntity> theOrders {get{...} set{...}}
    }

    other case for CustomerEntity is:

    interface ICustomerEntity : ICustomerData
    {
    IList<OrderEntity> theOrders {get;set;}
    }

    class CustomerEntity : CustomerData, ICustomerEntity
    {
    IList<OrderEntity> theOrders {get{...} set{...}}
    }

    can i do that? If i must use POCO, Am i able to define the Id as int in CSDL but in CLR object define it as Nullable<int> ?

    Thank you
    Tuesday, May 4, 2010 4:00 AM

Answers

  • You should be able to do all that, although I don't know if the designer supports it all.  Some things to note:

    - You can't include interfaces in the mapping in your CSDL, but your entity types that are mapped in the CSDL can certainly implemenet interfacers.

    - You can map properties in your entities from unmapped base classes.  For example, ModelBase need not be in your CSDL at all, but the Id property that it declares can still be mapped as the primary key property in all entities that derive from it.  If you try to oput ModelBase into your CSDL you might get things to work, but in my experience it's harder tp do.

    - It's okay to have the Id nullable in the entity but keep in mind that EF will often throw if you try to do anything with an entity that has a null key.

    - You may run into issues with this, "i need to create my entities run-time in future".  I'm not sure what you mean by this exactly (different people mean different things when they say this) but keep in mind that you cannot add new entities to a model/context that already exist.  In other words, once you define your model and create a context from it, then that model is fixed.  You could in theory update your CSDL, etc with you entities at runtime and then create new contexts based on that, but it's not a trivial thing to implement.

    Hope this helps.

    Thanks,

    Arthur

    Friday, May 7, 2010 4:35 PM

All replies

  • You should be able to do all that, although I don't know if the designer supports it all.  Some things to note:

    - You can't include interfaces in the mapping in your CSDL, but your entity types that are mapped in the CSDL can certainly implemenet interfacers.

    - You can map properties in your entities from unmapped base classes.  For example, ModelBase need not be in your CSDL at all, but the Id property that it declares can still be mapped as the primary key property in all entities that derive from it.  If you try to oput ModelBase into your CSDL you might get things to work, but in my experience it's harder tp do.

    - It's okay to have the Id nullable in the entity but keep in mind that EF will often throw if you try to do anything with an entity that has a null key.

    - You may run into issues with this, "i need to create my entities run-time in future".  I'm not sure what you mean by this exactly (different people mean different things when they say this) but keep in mind that you cannot add new entities to a model/context that already exist.  In other words, once you define your model and create a context from it, then that model is fixed.  You could in theory update your CSDL, etc with you entities at runtime and then create new contexts based on that, but it's not a trivial thing to implement.

    Hope this helps.

    Thanks,

    Arthur

    Friday, May 7, 2010 4:35 PM
  •  

    Hi,

     

    Could I define this:

     

    class CustomerEntity : CustomerData, ICustomerEntity

    {

    public virtual ICollection<IOrderEntity> theOrders

    {

     get

     {

      if (_theOrders == null)

      {

       var newCollection = new FixupCollection<IOrderEntity>();

       newCollection.CollectionChanged += FixupOrders;

       _theOrders = newCollection;

      }

      return _theOrders;

    }

    set {...}

    }

     

    Thank you


     

    Tuesday, May 11, 2010 8:11 AM
  • I missed that you had relationships defined in terms of your entity interfaces.  That won't work because the relationships in the model need to be defined in terms of types that are mapped in the model, and you can't directly map the interfaces in the model.  This is a known pain point.

    Thanks,

    Arthur

    Tuesday, May 11, 2010 4:31 PM
  • Hi,

     

    It's painful because we are unable to perform tasks that based on interfaces like TDD with Mock or dependency injection. ("unable" means that performing these tasks with interfaces are have lower cost and efforts, so performing them with concrete classes need more effort)

     

    Saeed 

    Wednesday, May 12, 2010 3:46 PM
  • @Saeed, @Arthur

    Has this issue been fixed in an update or is it still (as of today) not possible to have navigation properties defined as interfaces??

    Coming from NHibernate land (been there for many years) I was quite shocked that EF4 (yes version 4) does not handle such a simple thing. I think I heard that EF4 made the POCO style possible - but without ability to use interfaces how can people say that POCO is supported? We still have to design our domain layer in accordance to EF4 intricacies

     

    Pleae tell me that I'm missing something ;-)

     

     

    Regards Morten

    Monday, February 7, 2011 7:26 PM