I really want to be able to use NodaTime in my Entity Framework Code First database projects but haven't found a "clean" way to do it. What I really want to do is this:
public class Photoshoot
{
public Guid PhotoshootId{get; set;}
public LocalDate ShootDate{get; set;} //ef ignores this property
}
Is there any supported or recommended approach to using NodaTime with EF Code First?
Until custom primitive type persistence is natively supported in Entity Framework, a common work around is to use buddy properties.
For each custom primitive within your domain model, you create an associated mapped primitive to hold the value in a format supported by Entity Framework. The custom primitive properties are then calculated from the value of their corresponding buddy property.
For example:
public class Photoshoot
{
// mapped
public Guid PhotoshootId{get; set;}
// mapped buddy property to ShootDate
public DateTime ShootDateValue { get; set; }
// non-mapped domain properties
public LocalDate ShootDate
{
get { // calculate from buddy property }
set { // set the buddy property }
}
}
We use NodaTime in our code first POCO's using exactly this approach.
Obviously this leaves you with a single type acting as both a code first POCO and a domain type. This can be improved at the expense of complexity by separating out the different responsibilities into two types and mapping between them. A half-way alternative is to push the domain properties into a subtype and make all mapped buddy properties protected. With a certain amount of wanging Entity Framework can be made to map to protected properties.
This rather splendid blog post evaluates Entity Framework support for various domain modelling constructs including encapsulated primitives. This is where I initially found the concept of buddy properties when setting up our POCO's:
http://lostechies.com/jimmybogard/2014/04/29/domain-modeling-with-entity-framework-scorecard/
A further blog post in that series discusses mapping to protected properties: http://lostechies.com/jimmybogard/2014/05/09/missing-ef-feature-workarounds-encapsulated-collections/
EF Core 2.1 has a new feature Value Conversions, which is exactly for this scenario.
//OnModelCreating
builder.Entity<MyEntity>
.Property(e => e.SomeInstant)
.HasConversion(v => v.ToDateTimeOffset(), v => Instant.FromDateTimeOffset(v));
.HasConversion has some other overloads to make this logic re-useable, for example you can define your own ValueConverter.
No "clean" way that I'm aware of because EF, as of this writing, doesn't have a mechanism for simple type conversion like you see in NHibernate (IUserType). A real limitation in EF as an ORM which causes me to change my domain to suit my ORM.
There is a provider specific way that works with Postgres (Npgsql).
Install the library
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime
And then while configuring DbContext, use this,
services.AddDbContext<PhotoshootDbContext>(opt =>opt.UseNpgsql(Configuration.GetConnectionString("ConnectionString"), o => o.UseNodaTime()));
There are some third party libraries for other providers too.
Related
I am playing around building some buildingblocks based on database tables.
So I've created an UsersManager and a ValidationManager both based on the EDMX "templates".
I'd really like to loose couple those two components with MEF. But therefore i need to create Interfaces of the entityobjects exposed in the ValidationManager.
Is there an easy way of creating those Interfaces, in that manner i can still use the EDMX generated classes?
Thanx,
Paul
Using an example of a database with a Product Table, is this what you're trying to achieve....
but still use generated entity classes (using either the standard EF generator or another POCO generator of some sort).
I'm not sure - as you mention MEF and I don't see it being directly related.
The generated entity classes are partial classes which will allow you to extend the generated class which in this case you want to extend to implement an interface.
Presuming the following interface is going to be used to introduce the layer of abstraction...
public interface IEntity {
public bool IsDeleted { get; set; }
}
Create a new class file with and extended Product class...
public partial class Product : IEntity {
public bool IsDeleted {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
}
You have now extended your generated entity Product with the partial class custom code - and you can use it as normal through EF.
Now instead of your UserManager and ValidationManager classes having a hard reference to Product, instead they'll only have reference to IEntity.
If I didn't understand the question, please provide more details on exactly it is you want to do.
Suppose I have some Interface like :
public interface IIconComponent
{
// statements ...
}
then I am implementing this interface within my class as below
public class IconComponent : IIconcomponent
{
// implementing the interface statements ..
}
and creating a Table in mvc3 like:
public class IconDBContext : DbContext
{
public DbSet<IIconComponent> Icon {get; set;} //Is this statement possible
}
That is making the set of objects of interface type for storing the class IconComponent objects in the table. How to do this in MVC3 ?
Does I have to implement some model-binder for this ? or, there exists some other method ?
Thanking you,
EF doesn't support interfaces. DbSet must be defined with the real implementation. Once you change it to use implementation your actions will most probably use it as well because there will be no reason to work with abstraction.
Why would you use entity framework is you're creating abstraction layer on top of it, it's as you're not using entity framework at all and because of that entity framework is not able to work with interfaces.
If you really need to, you can let your Entity Framework classes implement interfaces. With POCO's it's straightforward, with edmx you can make partial classes that contain the derivation from the interface. However, as said by Ladislav, something like DbSet<IIconComponent> is not possible.
I can imagine scenarios where you would want to use this, e.g. dealing with other application components that only accept specific interfaces, but that you want to populate with your EF classes. (The other day, I did exactly that with a legacy UI layer).
Is it possible to map a table column to a class field instead to a class property and how?
YOU CAN DO IT :)
Follow this link: http://weblogs.asp.net/ricardoperes/archive/2013/08/22/mapping-non-public-members-with-entity-framework-code-first.aspx
This is a common request, and really makes sense; we need to use LINQ expressions and a bit of reflection magic. First, an helper function for returning an expression that points to a member:
public static class ExpressionHelper
{
public static Expression<Func<TEntity, TResult>> GetMember<TEntity, TResult>(String memberName)
{
ParameterExpression parameter = Expression.Parameter(typeof(TEntity), "p");
MemberExpression member = Expression.MakeMemberAccess(parameter, typeof(TEntity).GetMember(memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Single());
Expression<Func<TEntity, TResult>> expression = Expression.Lambda<Func<TEntity, TResult>>(member, parameter);
return (expression);
}
}
Then, we call it on the DbContext.OnModelCreating method, as a parameter to StructuralTypeConfiguration.Property:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Project>().Property(ExpressionHelper.GetMember<Project, Decimal>("Budget")).IsRequired();
base.OnModelCreating(modelBuilder);
}
Entity Framework (Code First or not) does not support mapping to a field; only to properties.
UPDATE
As pointed out in the comments, these documents are a bit dated but might still help any beginner along:
Entity Framework Code first development Resources and Documentation
For the sake of completeness, heres a link to whats included in EF 4.1 RC: EF 4.1 Release Candidate Available
Changes since CTP5 (From the link above):
Rename of ‘DbDatabase’ to ‘Database’. This class has also moved
to the ‘System.Data.Entity’
namespace, along with the database
initializer classes.
Rename of ‘ModelBuilder’ to ‘DbModelBuilder’, to align with the
other core classes.
Validation in Model First and Database First. The new validation
feature was only supported in Code
First in CTP5. In RC the validation
feature will work with all three
development workflows (Model First,
Database First, and Code First).
Complete Intellisense docs. Feature CTPs were not extensively documented
because the API surface was changing
significantly between each release.
This release includes complete
documentation.
Removal of Code First Pluggable Conventions. Pluggable Conventions
were previewed in Feature CTP5 but
were not at go-live quality for this
release. This release still supports
the removal of default conventions.
Consolidation of IsIndependent in the Code First relationship API. When
configuring relationships in Feature
CTP5 the IsIndependent method was used
to identify that the relationship did
not have a foreign key property
exposed in the object model. This is
now done by calling the Map method.
HasForeignKey is still used for
relationships where the foreign key
property is exposed in the object
model.
I'm using entity framework designer to build entities. I found the designer really hard to use because it overwrite all your manually change after each model update using the designer. How did you round off this problem? Thanks!
What sorts of things are you manually changing? The entity still has to be mappable to the database schema.
You can extend or add functionality by declaring a partial class.
Don't make any change to the entities in the generated file -- I think it says that in the header.
All of the entities are generated as partial classes, which means you can declare "more" of the class elsewhere.
Here is an example:
public partial class Name
{
public string First { get; set; }
}
public partial class Name
{
public string Last { get; set; }
}
Although I have two different class declarations, potentially in different files and folders within the project, it gets compiled as one class.
I can now use the Name class like this:
var name = new Name();
name.First = "Jane";
name.Last = "Doe";
As you can see, the properties from both declarations are unified in an object of type Name.
To apply this to EF, leave the partial entity class alone, and declare a separate partial class with the same name to add functionality.
There is an alternative third-party tool. For more information, refer this. Currently, Devart Entity Developer doesn't include the Update From Database functionality. The Update From Database feature is on our roadmap.
I have a Foo entity in Entity Framework. But I'm making it inherit from IFoo so that my business logic only knows IFoo - thus abstracting Entity Framework away.
The problem is that Foo has a collection of Bar entities. And this collection is of type EntityCollection<Bar> .
If I put this collection in IFoo as it is, I make IFoo dependent on Entity Framework. So I thought of putting it as ICollection<IBar>, but this doesn't compile (naturally).
The only solution I can think of is to go to the concrete Foo implementation generated by the Entity Framework designer and change the collection from EntityCollection<Bar> to ICollection<IBar> there. But I dread the thought of the implications this will have on Entity Framework "behind the scenes".
Is there any way for me to define IFoo and IBar independently of Entity Framework while still maintaining Foo and Bar as EF Entities that implement them? Do IFoo and IBar even make sense, if I cannot achieve this independence that I aim for?
The general concept you are referring to is "persistence ignorance" (PI), although that generally applies directly to entities themselves rather than the code that consumes the entities.
In any case, Hibernate and NHibernate natively support PI, but the initial version of Microsoft's Entity Framework does not. MS caught a lot of flak for this and PI is probably the #1 most discussed feature for the next version (whenever that is).
As far as what you are trying to do with interfaces, does the collection of Bars need to be modified after it is retrieved? If the answer is yes, there is no easy answer. Even covariance couldn't help you here because ICollection<T> has an Add method.
If the collection is read-only, then you might consider exposing it as IEnumerable<IBar>. The Enumerable.Cast method makes this fairly convenient.
interface IFoo
{
IEnumerable<IBar> Bars { get; }
}
partial class Foo : IFoo
{
IEnumerable<IBar> IFoo.Bars
{
get { return Bars.Cast<IBar>(); }
}
}
Also, I know of at least one effort to make the current version of EF support persistence ignorance.
I'm a Java developer, so I can't comment with any authority on Entity Framework. I can tell you that ORM solutions like Hibernate make it possible to have POJO persistence without having to resort to common abstract classes, interfaces, or modifying byte code. It handles relationships like the 1:m you cite for your Foo and Bar without having to use special collection classes.
The special sauce is externalized into mapping configuration and Hibernate itself.
The little bit that I read about Entity Framework suggests that it's an ORM solution with the same aim: POCO persistence. I didn't see any mention of interfaces. I can't see the need for them from your example, because it's too abstract.
I'm inferring that it's possible to get that independence between business objects and persistence tier without having to resort to those interfaces, because I know Hibernate does it. I'd say that Spring's JDBC solution accomplishes it as well, because there's no need for common interfaces. They use a RowMapper construct to ferry data out of a query and into an object.
I wish I could advise you precisely how to do it with Entity Framework, but maybe you'll take heart knowing that it can be done.
I recently wrote a comprehensive post about this: Persistence Ignorance in ADO.NET Entity Framework. You might want to look at EFPocoAdapter. That does just this and it will eventually deprecate into EF v2.
For what it's worth, I am using EFPocoAdapater and it's been working well for me.
We've been doing the exact same thing for LINQ to SQL. I got around the collection issue by writing a class which wraps an IList and casts to and from the correct type as required. It looks a bit like this:
public class ListWrapper<TSource, TTarget> : IList<TTarget>
where TTarget : class
where TSource : class, TTarget
{
private IList<TSource> internalList;
public ListWrapper(IList<TSource> internalList)
{
this.internalList = internalList;
}
public void Add(TTarget item)
{
internalList.Add((TSource)item);
}
public IEnumerator<TTarget> GetEnumerator()
{
return new EnumeratorWrapper<TSource, TTarget>(internalList.GetEnumerator());
}
// and all the other IList members
}
EnumeratorWrapper similarly wraps an IEnumerator and performs the casting.
In the LINQ to SQL partial classes we expose the property like this:
public IList<ICustomer> Foos
{
get
{
return new ListWrapper<Foo, IFoo>(this.Foos_internal);
}
}
Any changes to the exposed list will be performed on the internal EntitySet so they stay in sync.
This works well enough but my feeling is that this whole approach is more trouble than it's worth, I'm a huge NHibernate fan and a strong believer in P.I. but we've put in a LOT of extra effort doing this and haven't really seen any advantage. We use the repository pattern to abstract away the actual DataContext access which I would say is the key part of decoupling ourselves from LINQ to SQL.
Use a partial class to seperate your logic and rules from the autogenerated EF objects. In the example below FooEntityObject class is split into two using the partial keyword. I've used this technique before with EF and LINQ to SQL. The partial classes can be stored in seperate files so if your regenerate your EF object again your custom code doesn't get overwriten.
interface IFoo
{
public ICollection<IBar> GetBars();
}
public partial class FooEntityObject : IFoo
{
public ICollection<IBar> GetBars()
{
// convert EntityCollection<Bar> into ICollection<IBar> here
}
}
public partial class FooEntityObject
{
EntityCollection<Bar> Bars{get;set;}
}