Using the same classes for NHibernate and Script#? - c#

I am about to start a project using NHibernate and Script#
NHibernate required that all properties be virtual, so I have my entity like this:
public partial class User
{
public virtual string Username { get; set; }
public virtual string PasswordHash { get; set; }
public virtual DateTime DateRegistered { get; set; }
}
But Script# build fails when it encountered partial and virtual.
Partial I can cope with but not having virtual will probably requires a redesign/thinking ahead.
My goal is to share code between the main models project and the front-end Script# project so I don't have to re-implement the model twice, have strong-typing support and refactoring support throughout the models and scripts etc. etc.
Is this possible? Has anyone done this before? What are some available options?

I would create a ViewModel, and use AutoMapper to perform mapping for you, then you can use Script# with ViewModel.

Related

Writing Range Data Annotation with Fluent API in Entity Framework Core

Description
As I'm trying to adopt Clean Architecture, I want to move away from Data Annotations and use Fluent API which, personally, I started to prefer a lot more.
However, I'm not too skilled in this way of implementing things.
Range Annotation (Old approach)
What I was previously doing was to use the Range annotation to specify a min and a max for number properties like so:
public class Engine
{
...
[Range(0, 10000)]
public int Size { get; set; }
[Display(Name = "Horse power")]
[Range(0, 1000)]
public int HorsePower { get; set; }
[Display(Name = "Top speed")]
[Range(0, 500)]
public int? TopSpeed { get; set; }
...
}
Configuration class (Cleaner approach)
Now, I'm trying to write the validation code in the Configuration class associated with the Engine entity.
The entity class:
public class Engine
{
public int EngineId { get; set; }
public int Size { get; set; }
public int HorsePower { get; set; }
public int? TopSpeed { get; set; }
public int FuelId { get; set; }
public int TransmissionId { get; set; }
}
This is what I currently have for the Configuration class:
using Carsurfer.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Carsurfer.Persistence.Configurations
{
public class EngineConfiguration : IEntityTypeConfiguration<Engine>
{
public void Configure(EntityTypeBuilder<Engine> builder)
{
builder.Property(engine => engine.Size);
}
}
}
Questions
Is there something built in to Entity Framework Core for this?
Should I implement the IValidatableObject interface somehow?
Should the Configuration class be concerned with the validation of its entity?
Is there something built in to Entity Framework Core for this?
There is no Fluent API equivalent to RangeAttribute to the best of my knowledge.
Should I implement the IValidatableObject interface somehow?
Implementing IValidatableObject won't enable you to use Fluent API for RangeAttribute. You would still have to use DataAnnotation attributes.
Should the Configuration class be concerned with the validation of its
entity?
IEntityTypeConfiguration is meant to provide a clean way to separate the your DbModel configuration for EntityFrameworkCore to use. So typically such configuration class will contain schema level set up and validation (constraints, max values, relational configuration (where appropriate)).
The question you need to ask yourself is why you are even using RangeAttribute in the first place. It does not have any effect schema wise. You could be using it because you also use your entity classes for MVC in built validation. If that's the case and you share your entity (POCO) classes instead of having separate classes for your ViewModels or Dto's then you will have to just use a hybrid version where you separate data annotations that are EF Core related into IEntityTypeConfiguration classes and leave data annotations that are for MVC validation purposes as attributes. It is worth noting that DisplayNameAttribute is also irrelevant as far EF Core is concerned.

How to add new entity properties in Entity Framework without changing database model

I am new to Entity Framework. I started with database first approach which created my classes corresponding to the tables I selected. I am using MVC. One of my tables has a Date column in it. My requirement is I want to display the Day in my gridview(Grid MVC) i.e. if Date for that particular record fetched is 10/27/2015, then Day should show Tues. I want to do this without adding an extra column for the day in my database.
Is there a way for this. Any help will be greatly appreciated.
My model class generated is as below:-
public partial class QnsNew1
{
public int Id { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public Nullable<int> PersonelID { get; set; }
public string CType { get; set; }
public string Comments { get; set; }
//public string Day { get; set; }//I want to avoid doing this
public virtual Personnel Personnel { get; set; }
public virtual Type Type { get; set; }
}
A better approach
Although this can be easily done with Entity Framework, but as pointed out by other answers here, and I acknowledge 100%, that it is better to separate presentation/UI models from database models by creating ViewModel separate from your regular entities and put your calculated properties there.
If you are stuck with EF, keep reading
In EntityFramework Database First mode, the classes generated for the database model are partial classes. You can basically create another partial class with the same name and in the same assembly and namespace and add your calculated property there.
here is a complete example (after borrowing the day of week implementation from the answers here):
public partial class MyTable
{
[NotMapped]
public string DayOfWeek
{
get
{
if (Date.HasValue)
return DateTime.Now.DayOfWeek.ToString();
else
return null;
}
}
}
It is important that you make sure the namespace is the same as the generated class. Also you will must annotate that property with NotMapped attribute so that EF does not attempt to map or save that property back to the database.
Create a partial class by the same name and have a getter property called Day. This will not add a column to your database.
public partial class QnsNew1
{
public string Day
{
get
{
if (Date.HasValue)
return DateTime.Now.DayOfWeek.ToString();
else
return null;
}
}
}
You could add a partial class QnsNew1 { public DayOfWeek Day { get; set; } } next to your generated data/model. But I would probably suggest that you separate your DataModel from your presentation model and this is a good reason why. Your presentation model will have parts to it that are just used for presentation and are computed on the fly whereas your data model should just strictly represent your data that is persisted.
Consider using a view model instead of model created by entity framework. I do not prefer using database models in my views because of the issue that you are facing. Instead I create a view model and then copy data from database model to view model using AutoMapper or some library like that.

Persistent Ignorant Domain with Entity Framework and Spacial Data

I'm developing an application that implements DDD and Repository Pattern as shown in diagram bellow:
I expect to keep my Domain Layer persistent ignorant, so I wouldn't like to install entity framework libraries there. The only problem I'm facing is that my application uses spatial data, but I'm not supposed to use DbGeography as a Property Type of my entities, once it belongs to System.Data.Entity.Spatial namespace, from EntityFramework assembly.
Is there a way to create a class to hold latitude, longitude and elevation values in Domain Layer, like that:
public class Location
{
public double Latitude { get; set; }
public double Longitude { get; set; }
public double Elevation { get; set; }
}
and then convert that class to DbGeography in my Repository Layer?
In other words, the domain entities would have only Location class as a property:
public class Place : IEntityBase, ILocalizable
{
public int Id { get; set; }
public string Name { get; set; }
public Location Location { get; set; }
public User Owner { get; set; }
}
and I'd convert it DbGegraphy to persist spatial data and do some calculations only in repository layer. My plans was try something like that to convert:
public class LocationMap : ComplexTypeConfiguration<Location>
{
public LocationMap()
{
Property(l => DbGeography.FromText(string.Format("POINT({0} {1})", l.Longitude, l.Latitude))).HasColumnName("Location");
Ignore(l => l.Elevation);
Ignore(l => l.Latitude);
Ignore(l => l.Longitude);
}
}
But it doesn't work and never will. How I can solve this problem? What are the best practices in this situation?
Thank you
Well, I don't know "right" way, but, i have a tricky idea. I hope, it'll help you or give some more variants:
Ypu have domain entity Place, it's fully persistent ignorant and it's place in Domain assembly. Good.
Lets create one more Place class in Repository assembly:
internal sealed class EFPlace : Place
{
DbGeography EFLocation
{
get
{
return DbGeography.FromText(string.Format("POINT({0} {1})", Location.Longitude, Location.Latitude);
}
set
{
//vice versa convertion, I don't know, how to do it :)
}
}
}
We created special class for Entity Framework, and map it:
public class PlaceMap : ComplexTypeConfiguration<EFPlace>
{
public PlaceMap ()
{
Property(p => p.EFLocation).HasColumnName("Location");
Ignore(p => p.Location);
}
}
But, we have to convert from Place to EFPlace on save in repository. You can create special constructor, or casting method.
Another variant - create partial class Place in Domain and Repository assemblies. And add needed propery in Repository one class and so on.
Well, it looks ugly :( but, I don't know "pure", real-life examples of Persistent Ignorant Domain. We always have limitations of Entity Framework. NHibernate has a little more features.

How to use Fluent NHibernate Validator when using auto mapping?

I've just modelled a small database using Fluent nHibernate and the auto mapping feature. Now I'm wondering how I work with validation. In the past I've decorated my classes with attributes but the purpose of this by-convention automapping is to keep things clean.
I do have a couple override files which look like this:
public class EventMappingOverride : IAutoMappingOverride<Event>
{
public void Override(AutoMapping<Event> mapping)
{
mapping.Map(x => x.EventType, "TypeID").CustomType(typeof(EventType));
mapping.Map(x => x.EventStatus, "StatusID").CustomType(typeof(EventStatus));
mapping.HasMany(x => x.EventDates).KeyColumn("EventID");
}
}
Is this where I would put my validation rules? If so, what does that look like and is there really even a point to using the auto mapping (if my override files are going to be elaborate anyway)?
Thanks.
To clarify further:
My entities look like this as of now:
namespace Business.Data
{
public class Event
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual EventStatus EventStatus { get; set; }
public virtual EventType EventType { get; set; }
public virtual IList<EventDate> EventDates { get; set; }
}
}
I would like to keep them looking that like. Just plain objects so in the future we can potentially switch out or upgrade the ORM and still have these nice clean objects.
However, when it comes to using nHibernate Validator (part of NHContrib) I'm not sure how to incorporate it without littering the properties with attributes. I guess this is more of a question architecture. I could use a different validation framework as well but I want it to be tied in with nHibernate so that it won't insert/update invalid records. Any opinions appreciated!
My opinion is :
Validation is part of the business at it depend from it and then the database scale to this need. So if you need a email string column in your db you should not rely on a db framework to do that especially as you said that may be later you will switch ORM then you will loose your work.
Keep validation in the business/high layer, and leave the db do simple query/insertion, remember NHibernate is already a bit complicate to hand on so keep it simple.
To answer your question, if you don't want to littering your entities use the xml validation as describe here.
http://nhforge.org/wikis/validator/nhibernate-validator-1-0-0-documentation.aspx

Entity Framework - Multiple Project support

I am looking into migrate a large project to Entity Framework 4.0 but am not sure if it can handle my inheritance scenario.
I have several projects that inherit from an object in the “main” project. Here is a sample base class:
namespace People
{
public class Person
{
public int age { get; set; }
public String firstName { get; set; }
public String lastName { get; set; }
}
}
and one of the sub-classes:
namespace People.LawEnforcement
{
public class PoliceOfficer : People.Person
{
public string badgeNumber { get; set; }
public string precinct { get; set; }
}
}
And this is what the project layout looks like:
People - People.Education - People.LawEnforcement http://img51.imageshack.us/img51/7293/efdemo.png
Some customers of the application will use classes from the People.LawEnforcement and other users will use People.Education and some will use both. I only ship the assembles that the users will need. So the Assembles act somewhat like plug-ins in that they add features to the core app.
Is there anyway in Entity Framework to support this scenario?
Based on this SO question I'm think something like this might work:
ctx.MetadataWorkspace.LoadFromAssembly(typeof(PoliceOfficer).Assembly);
But even if that works then it seams as if my EDMX file will need to know about all the projects. I would rather have each project contain the metadata for the classes in that project but I'm not sure if that is possible.
If this isn't possible with entity framework is there another solution (NHibernate, Active Record, etc.) that would work?
Yes this is possible, using the LoadFromAssembly(..) method you've already found.
... but it will only work if you have an specialized model (i.e. EDMX) for each distinct type of client application.
This is because EF (and most other ORMs) require a class for each entity in the model, so if some clients don't know about some classes, you will need a model without the corresponding entities -- i.e. a customized EDMX for each scenario.
To make it easier to create a new model for each client application, if I was you I'd use Code-Only following the best practices laid out on my blog, to make it easy to grab only the fragments of the model you need actually need.
Hope this helps
Alex
Alex is correct (+1), but I'd strongly urge you to reconsider your model. In the real world, a police officer is not a subtype of a person. Rather, it's an attribute of that person's employment. I think programmers frequently tend to over-emphasize inheritance at the expense of composition in object oriented design, but it's especially problematic in O/R mapping. Remember that an object instance can only ever have one type. When that object is stored in the database, the instance can only have that type for as long as it exists, across multiple application sessions. What if a person had two jobs, as a police officer and a teacher? Perhaps that scenario is unlikely, but the general problem is more common than you might expect.
More relevant to your question, I think you can solve your actual problem at hand by making your mapped entity model more generic, and your application-specific data projections on the entities rather than entities themselves. Consider entities like:
public class JobType
{
public Guid Id { get; set; }
// ...
}
public class Job
{
public JobType JobType { get; set; }
public string EmployeeNumber { get; set; }
}
public class Person
{
public EntityCollection<Job> Jobs { get; set; }
}
Now your law enforcement app can do:
var po = from p in Context.People
let poJob = p.Jobs.Where(j => j.JobType == JobType.PoliceOfficerId).FirstOrDefault()
where poJob != null
select new PoliceOfficer
{
Id = p.Id,
BadgeNumber = poJob.EmployeeNumber
};
Where PoliceOfficer is just a POCO, not a mapped entity of any kind.
And with that you've achieved your goal of having a common data model, but having the "job type specific" elements in separate projects.

Categories