When using the SQLEntityConnection F# type provider, the generated types provided by this type provider may not be used by other F# assemblies and, by implication, any other assemblies, such as a separate ASP.Net application, console application, C# program, etc. So the type provider must be marked internal or private.
Moreover, functions that use the type provider may not be more accessible than the types provided by the type provider. So such functions must also be marked internal or private.
What is the proper way to map these types, which by necessity must be marked internal or private, to something public which can be used outside the same assembly?
A simple pattern using Entity Framework is to retrieve an entity from a DbContext, update some properties, call some methods, update some child entities, etc., then call SaveChanges() on the DbContext. Since the retrieved entity is still attached to the DbContext and the DbContext is still in scope, the changes are tracked automatically and the update is simple.
Is the same workflow possible using the SQLEntityConnection F# type provider? My guess is no if the entity needs to be updated outside the assembly where the TypeProvider is used, e.g. in a C# MVC project, given the limitations I mentioned in the original post. What is a comparable approach to doing basic CRUD operations using the SQLEntityConnection type provider? Unfortunately, the official documentation is very lacking in basic operations. Maybe an alternate type provider is a better, more functional choice.
Related
The design of EF forces developers to inherit the DbContext class. Some reusable libraries (such as ASP.NET Identity) typically provides its functionality using the same inheritance route, i.e. by providing the IdentityDbContext base-class.
But obviously this won't work if you have 2 such libraries, e.g. requiring you to inherit from IdentityDbContext and CmsDbContext at the same time, which is obviously impossible to do on .NET. The result that I want is to have an application-dbcontext that contains both the models from my identity module and my cms module (I won't be able to separate this to 2 dbcontexts since that would mean I will end up with multiple connections and transactions, and that my models can only reference to either identity or cms entities, but not both).
It's hard to believe that this question hasn't seemed to be asked around EF community, but this seems like a horrendously bad ORM design. Inheritance only lets you to have strictly linear modularisation. (As a comparison, in NHibernate, ISession and your Configuration are 2 separate things, therefore you can use discovery process to build up your mapping-configuration from different unrelated modules, without messing with my ISession and thus my db-connection/transactions).
So the question is, let's say you're a developer of a module that would like to register models into entity-framework (similar to ASP.NET identity module), you won't want to have a base DbContext that the consuming application must inherit, because it would prevent them from consuming other modules (e.g. ASP.NET identity's IdentityDbContext). So what are my options?
Is there any way to register models into a DbContext class without requiring to inherit from a DbContext? Is overriding OnModelCreating the only way to get access to a ModelBuilder?
I don't think your comparison is entirely fair. (Although I'm the first to admit that NHibernate beats EF in many areas).
With NHibernate, usually you load objects by some generic method in which you supply the type you want to load. You could create ISession implementations with hard-coded Query<T> (or QueryOver<T>) properties, like...
public Query<MyUser> Users { get; set; }
...and you'd have the same "problem" that you can't merge, or inherit from, two different implementations.
Likewise, you could work with EF by loading objects by using context.Set<T> only. You could even inject the configuration (sort of) by supplying EntityTypeConfiguration classes (as a list) in the context's constructor, storing them in a member variable and adding them to the model builder in the OnModelCreating override.
These specialized context classes, like IdentityDbContext, are offered to make life easier if they suit you. They have hard-coded DbSet properties (among others). The fact that you can't multiple inherit them is not a design flaw. It's just a (non-negotiable) language specification.
Choose the one that most closely serves your needs (propably CmsDbContext) and add other class mappings yourself.
Here is my set up thus far:
Database-First Entity Framework (generates a EDMX)
Separated POCOs into a different project
Left Custom DbContext under EDMX to be used as a bounded Countext
Created a UOW
Created a generic Repository (IRepository)
Mapped each entity into the UOW through concrete implementations of IRepository
UOW instantiates the Custom DbContext created by the EDMX and passes it along to each Repository
So far all is well.
Now, the problem stems out of that last part. The UOW instantiates the Custom DbContext, injects it into the Repositories and everything works... for the most part.
Each Repository implementation takes the DbContext, creates a DbSet and exposes the usual CRUD operations. All Entities are accessible through generics, so if I want to implement say GetAll() I will simply return DbSet and it will already be mapped to the Entity .
BUT, when I try to access a Function Import from DbContext within the Repository... I CAN'T.
It makes sense that I can't of course: the generic repository takes a DbContext as input, but it knows nothing of the Custom DbContext created by the EDMX, thus, all such functions added into the Custom DbContext are not known to the DbContext within the repository.
In other words:
I can access the Function Imports from the Custom DbContext while in the UOW
I pass the Custom DbContext to the constructor of each Entity Repository
The Repository expects any class that derives from DbContext, so the Custom DbContext does the trick
When the Repository tries to access the Function Import through the DbContext is has access to, it can't, because it has no knowledge of them
Obviously I can't just use the Custom DbContext everywhere, because I would be marrying the Repository to a specific Custom DbContext, and I'll be needing more than one since I'm created several Bounded Context.
Alas, THE QUESTION:
How could I call the Function Import from within the Repository without marrying it to a specific Custom DbContext?
Workarounds:
I know I could use reflection, but I'm trying to stir away from it for performance reasons (I know it is not that terrible, but still... the present question is about finding out a better way).
I have managed to get what I needed using DbContext.SqlQuery() to execute the Stored Procedure (which was mapped to the Function Import in the EDMX). Yet again, since I can easily swap Function Imports in the EDMX, I would like to find a way to access it within the Repository.
Hope it all makes sense. I appreciate any light anyone can shed onto the matter.
It's not clear to me how would you know what function to invoke or what parameters it takes. However you can take a look at the code generated for function imports and it basically looks like this:
((IObjectContextAdapter)this).ObjectContext
.ExecuteFunction<Customer>("Customers_With_Recent_Orders", customerId)
Therefore (instead of using reflection) you can just do the same thing dynamically - given that even with reflection you would have to know what function to invoke, you should know the type of the entity you expect and you can use params to pass any number of parameters it should be doable.
** EDIT **
You can also execute the function as no tracking by using the other overload:
((IObjectContextAdapter)this).ObjectContext
.ExecuteFunction<Customer>(
"Customers_With_Recent_Orders",
MergeOption.NoTracking,
customerId)
According to Initial POCO Design 1-Pager
Persistence Ignorance refers to being
able to allow the developer to write
and test domain objects in a way that
is entirely independent of fundamental
requirements and assumptions that may
be made by the infrastructure service
(in this case, the Entity Framework).
Such requirements / assumptions may
often include:
The need to implement a specific interface (for e.g., IPOCO)
Inheritance from a base class
Providing specific constructors
Object Instantiation/Construction requirements – use a specific factory
for instance**
The need for metadata or mapping class or property Attributes
The need to use specific relationship mechanisms
This amounts to being able to use
Plain Old CLR Objects (POCO) so that a
developer can author their domain
objects free of all assumptions and
requirements imposed by the framework.
Using this approach, once the domain
objects are ready to their
satisfaction, the developer can use
these classes with the Entity
Framework in order for relational
database access and persistence.
As of right now (CTP5), is there any way at all to reconstitute a poco using a parametrized constructor? If not, it's hard to see how the Entity Framework can be said to offer persistence ignorance.
You can have as many parameterized constructors as you want, so long as the framework has access to a parameter-less one, which is available by default if you you have no constructors, or if you provide one in addition to the parameterized ones you create.
How i can use Inheritance in Entity Framework with .NET RIA Services?
Problem:
if there is inheritance in EF, silverlight application don't compiled.
Can you help me?
This:
Type 'Common.Individual' is a direct or indirect subclass of Type 'Common.Customer'. DomainServices cannot return a Type that is a subclass of another Type returned from the same DomainService.
...does not mean "no inheritance support." It does mean that (in the current version of RIA services) you can't return both a parent and a child type to the client.
That is a limitation, and it's a limitation you have to live with in RIA Services for now. That said, I don't think it's as big as a limitation as the thread you reference implies. Is not the same as saying you cannot use inheritance at all. Also, I think that inheritance tends to be overused in entity mapping for reasons I explain in great detail in this presentation.
So while I can't fix the limitation, my suggestions are:
Use composition instead of inheritance when appropriate (cf. the presentation referenced above).
When you must use inheritance, RIA Services will require that you don't return the parent type.
Aside from faster development time (Visual Studio 2010 beta 2 has no T4 templates for building POCO entity objects that I'm aware of), are there any advantages to using the traditional EntityObject entities that Entity Framework creates, by default? If Microsoft delivers a T4 template for building POCO objects, I'm trying to figure out why anybody would want to use the traditional method.
You're asking two questions at the same time, it seems. Code-only versus model-first and EntityObject parent type versus arbitrary parent type. You get designer support with model-first, regardless of parent type. Aside from designer support, you can also use precompiled views with model-first. That can significantly help performance.
Having EntityObject as a parent can be an advantage over so-called "POCOs" (which are usually proxy bases, not "plain" objects), because the runtime type of your entities are the exact type you expect, rather than a runtime-generated subtype.
Also, unlike other ORMs which have minimal to no LINQ support, the Entity Framework has rich LINQ support, allowing you to project onto real POCO types. Therefore, it is possible to build truly persistence-ignorant presentations without having to care about what the base type of your entities are. You are not stuck with whatever type comes out of the ORM blackbox.
EntityObject allows for private properties which are persisted to the database. Using proxy types requires that those properties are at least protected and must be virtual. Therefore, EntityObject may allow for better encapsulation.
I'm not trying to suggest, by the way, that there aren't advantages to using proxies; I'm just trying to answer your question about what the advantages of EntityObject are.
I think the only benefit is designer support. Can't find any other benefits in using non-poco entities.