I have three tables that have the following relationships between them:
Account {
public int Id;
}
Job {
public int Id;
public int AccountId;
}
Practice {
public int Id;
public int AccountId;
public string Name;
}
I would like to be able to access a Practice object through a Job object like so:
Job.Account.Practice.Name
The database structure is pre-existing, so changing it is not an option. I would like to get EF to provide access to this relationship, and I'm sure it can. I did get it to work by putting an ICollection navigation property to Practice on the Account class and annotating an Account navigation property on the Practice class with ForeignKey, but there has to be a way to do it without using a collection.
So, the question is, what data annotation attributes should I attempt to use to get the desired result?
Description
You need no DataAnnotation Attribute to do that. In Codefirst you can do the following. The Entity Framework will generate the table you described for you.
Sample
Account {
public int Id;
}
Job {
public int Id;
public virtual Account Account;
}
Practice {
public int Id;
public virtual Account Account;
public string Name;
}
If you want also a ìnt column (AccountId) in your Job / Practice Entity you can do this using the ModelBuilder. The Entity Framwork creates only one foreign key column, like you want.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Job>.HasRequired(x => x.Account).WithMany().HasForeignKey(x => x.Accountid);
//
}
More Information
ScottGu - Using EF “Code First” with an Existing Database
Update
You can use Entity Framework Power Tools CTP1 to generate the
Models from your existing Database.
Related
I'm new to dependency injection but fast becoming a big fan. However I can't seem to find anything that satisfactorily describes how to deal with objects at run time which are not injected from a container. I'll refer to same as data objects.
Consider the following, (forgive me if the following shows I've completely missed the point of DI):-
In the old days I would code an object as follows: -
public class Person
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public void DoSomething(params string[] paremeters)
{
//code to do something with this person using parameters
}
public void DoSomethingElse()
{
//code to do something else with this person
}
}
Now with DI I might do the following: -
public class Person
{
public string Name { get; set; }
public string EmailAddress { get; set; }
}
public interface IPersonService
{
void DoSomething(Person person, params string[] paremeters);
void DoSomethingElse(Person person);
}
public class PersonService : IPersonService
{
public void DoSomething(Person person, params string[] paremeters)
{
//code to do something with this person using parameters
}
public void DoSomethingElse(Person person)
{
//code to do something else with this person
}
}
And the IPersonService service would be 'injected' through constructors into any processes that needed it. The problem is that it feels wrong having to add a Person parameter to every procedure and method in the PersonService but no alternatives seem to work any better.
For example I could use something like
Person _person;
void Configure(Person person)
{
_person = person
}
..in all my injected services which needed transient data, but then you run into state problems and all such services need to be transient. Again not happy with that.
In this example the person might come from a database, a screen form, a file, have been selected from a list in a directory or anywhere else.
I am aware that I could inject my data using a data repository (class to access the data and all the CRUD stuff) and indeed I have every intention of doing that but that still doesn't solve the problem of how I tell the service, in this case, which person to access unless of course I add a procedure into the service which includes a parameter for the identity of the person and then use the repository to go and fetch the person... but that then works just like the Initialise approach which results in State problems. It also relies on remembering to call the procedure in the service to configure the data.
My question is, what's the best practise here? Please keep it simple.
Many thanks
I am using Entity framework 5 and using repository pattern. Say I got these entities Customer, Files, Images, Tasks, Invoice, User.
Each entity (apart from Customer) has a foreign key of Customer. When a user logs in I store the customerid in session (aps.net mvc). What I want is any CRUD taken on all entities to be limited to the customer who's user is logged in. e.g I can't afford to delete a Task belonging to customer 1 to be deleted by user who is from customer 2.
Is adding an argument of customerid for each method of repositories the best way to achieve this or are there any better/clever ways of doing it?
Tricky to give a definitive answer but you could make it a bit more extensible by implementing higer order functions, like this:
public interface IRepository<T>
{
public T GetBy(Expression<Func<T, bool>> query)
}
public class FileRepository : IRepository<File>
{
public File GetBy(Expression<Func<T, bool>> query)
{
using(var context = new FilesContext())
{
return context.Files.Where(query).FirstOrDefault();
}
}
}
public class SomeController
{
private IRepository<File> _repo;
public SomeController(IRepository<File> repo)
{
_repo = repo;
}
public ActionResult Index()
{
var model = _repo.GetBy(f => f.CustomerId == Session.Whatever.CustomerId);
return View(model);
}
}
This way you can vary the search query when required, rather than tie yourself in to using a hardcoded customer id property. For example, if you wanted to get the File object by the FileID, not the CustomerID, then:
var model = _repo.GetBy(f => f.FileId == someId);
and that's the only part of the code that needs to change.
Some really good info on Higher Order functions and functional programming in C# here: http://www.codeproject.com/Articles/375166/Functional-programming-in-Csharp
Edit:
You might be able to isolate the "Always use the customer ID when hitting DB" into a repository of it's own, using a decorator style pattern, thus: (massive disclaimer - I haven't tested this, but something along these lines should work)
public class SpecialFileRepo : IRepository<File>
{
private readonly IRepository<File> _baseRepo;
public SpecialFileRepo(IRepository<File> baseRepo)
{
_baseRepo = baseRepo;
}
public SpecialFileRepo() : this(new FileRepository())
{
}
public File GetBy(Expression<Func<File, bool>> query)
{
var parameters = query.Parameters;
var newParam = Expression.Parameter(typeof (File), "f");
var additionalQuery = Expression.AndAlso(query.Body,
Expression.Equal(
Expression.PropertyOrField(newParam, "CustomerId"),
Expression.Constant(HttpContext.Current.Session["customerId"])));
var newQuery = query.Update(additionalQuery, parameters);
return _baseRepo.GetBy(newQuery);
}
}
Then anything that's talking to a repository, as far as it's concerned, it's just a base repository, but this class is sitting in between and always grafting the "customerid = sessionwhatever" expression onto what finally gets passed to the database. And of course, anything that only cares about using the base repository, can still do so.
I wish to give a Person as defined below, the ability to print a vCard out of my system. To provide the user with privacy options, the user can select whether to show/hide certain properties. In it's simplest form, I need to have a separate table that would hold the user's choices.
I was wondering if it was possible to build this configurator table using reflection. As shown in the Person model below, I could decorate properties with a custom attribute, and then using those properties, construct and persist a model that would have a bool property for every decorated Person property.
public class Person
{
public string UserName { get; set; }
public string FirstName { get; set; }
[DisplayOnVCard]
public string LastName { get; set; }
[DisplayOnVCard]
public string Email { get; set; }
[DisplayOnVCard]
public string MobilePhone { get; set; }
}
** where [DisplayOnVCard] is a custom attribute.*
At the end of this, I expect a table in the db that would correspond to this:
public class VCardConfigurator
{
public bool LastName { get; set; }
public bool Email { get; set; }
public bool MobilePhone { get; set; }
}
This is just a sample representation of what is actually a huge entity. Which is why I hope to avoid manually mapping a bool field to each optional property.
I believe this problem domain is quite similar to how, for instance, privacy settings work on social networking sites, yes?
While I was typing this, I did ponder upon the possibility that if down the line I was to remove the attribute from one of the properties, what implications that might have. Needs some thought!
Further reading for self:
Programmatically adding properties to an MVC model at runtime
There is a huge possibility that I am galloping down a totally wrong path! If that is the case, please advice so!
#1 Update
I am not sure its possible to add or remove attributes for an instance since attributes are at the class level, but their property values can be changed (Since they are instances).
My suggested solusion
I am not sure what you mean in "I expect a table in the db that would correspond to this",
since you can't have a table in the database that contains only the columns of the non-privacy properties for each user.
You will need a dedicated table for this mapping (Lets say 'PrivacyMappings' table), with these columns:
UserId, PropertyName, IsPrivate.
When a user is added, all the properties will be added to this table with a default privacy settings (for instance, all properties are non-private by default).
You can add the properties by iterating over them and insert them as you said.
You can use the following class in entity framework:
public class PrivacyMapping
{
public int UserId {get;set;}
public string PropertyName {get;set;}
public bool IsPrivate {get;set;}
}
Adding the default privacy settings when a user being added:
// retrieve user model properties.
foreach (property in properties)
{
//iterrate over the user Properties.
context.PrivacyMapping.Add(new PrivacyMapping(user.userId, propertyName, isPrivate);
}
context.SaveChanges()
Now you can take all the user non-private properties by
context.PrivacyMapping.Where(p=>p.UserId == user.id && !IsPrivate).Select(p=>p.PropertyName);
And now you can deal with information any way you want.
For example, you can have a VCardItems class, that receive an user id/object in its c'tor and stores a dictionary of the allowed properties by their names.
public class VCardItems{
private Dictionary<string, object> properties{get;set;}
public VCardItems(User user)
{
// initiate values..
}
public object this[string name] {
get
{
if (properties.ContainsKey(name))
{
return properties[name];
}
// A private property.
return null;
}
set
{
properties[name] = value;
}
}
}
There is other options of how to use the data, for example with ActionFilter that in this case sets the private properties to null or storing the non-private data in the HttpContext.Items dictionary,
but it really up to you.
First message
Before we get into details, I wonder how you expect to use this class.
If a view (or whatever going to handle it), going to receive have a runtime-generated class for example, how you gonna handle it?
How you gonna know what properties this model has?
I am working on asp.net MVC 3 application and I am using codeFirst approach. I am trying to create history table or user table, Where I want to keep track of what columns were modified by user. How can I do this using EF Code First.
Do I need to do it after DataContext.savechanges ?
Please suggest.
Thanks.
The DbContext has a method called Entry<T>:
var entity = context.Items.Find(id);
entity.Name = "foobar";
var entry = context.Entry<Item>(entity);
entry will be of type DbEntityEntry<T> and has the properties OriginalValues and CurrentValues.
You could probably write something that will generically inspect these properties to see what has changed and then automatically insert a new record into your history table.
Either that, or use database triggers.
I'm not sure if this is really the "appropiate" way to do it, but this is how its usually done in sql:
Create an extra property version of type int or something.
Because you probably do not want to loop every time, add another property IsLatestVersion of type bool
When an entity is saved, check if the entity already exists. If so, set the entity on IsLatestVersion = false.
Increment the version, and save the changes as new entity.
Sounds to me like you want an a filter that inherits from ActionFilterAttribute. In my case, this is the simplest example that I have. This is my model, notice that the attributes dictate the mapping to the database.
[Table("UserProfile")]
public class UserProfile
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
In my case, it was as simple as the following, although it was not historical:
public sealed class UsersContext : DbContext
{
public UsersContext() : base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
LazyInitializer.EnsureInitialized(ref _initializer, ref isInitialized, ref initializerLock);
}
public void CheckDatabase()
{
Database.SetInitializer<YourDBContextType>(null);
using (var context = new YourDBContextType())
{
if (!context.Database.Exists())
{
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
// Uses your connection string to build the following table.
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
The end result is not only EF being code first, but also allows for your models for your views to use primitives derived from your complex entities. Now, if you have another, lets say historical, DBContext then I would recommend modifying either the text transformation file or creating a base class for your entities. Both ways allow for an easy generation of code that could insert into your table, then follow up with that entity, clone it into a historical model and save. All that being said, I am a fan of database first approaches with concentration on constraints, triggers, etc. instead of a framework.
I'm writting an ASP.NET MVC e-commerce app using NHibernate and I want the end-user to be able to control the ordering of Product Categories (not just have them appear alphebetically etc.).
Normally, I'd add an OrderIndex/Sort column (of type int) to the Category table, and property to the Category domain class. But the problem is in having to constantly manage this special OrderIndex/Sort column as Categories are sorted, added, and deleted. I'd rather hide it away and make it transparent so callers don't have to set the property directly.
Sure I could write my own code to manage all this, but wanted to know if NHibernate has anything built in that could help me, or if it could hook this property up automatically.
If not then I was thinking of creating an OrderedEntity base class (all domain objects derive from an Entity base), and create an IOrderedRepository base Repository as well. Something like this:
public class Entity
{
public virtual int Id { get; set; }
}
public class OrderedEntity : Entity
{
public virtual int OrderIndex { get; set; }
}
public class Category : OrderedEntity
{
}
public interface IRepository<T> where T : Entity
{
T FromId(int id);
void Save(T entity);
}
public interface IOrderedRepository<T> : IRepository<T> where T : OrderedEntity
{
void MoveUp(int places);
void MoveDown(int places);
}
Does this seem like a good approach? I don't want to reinvent an inferior wheel.
So far I know Hibernate has an annotation #OrderBy where you can specify the ordering when the collection is loaded. But Hibernate won't manage the position that for you when you add or remove element in the collection.
You can however easily do that yourself and provide methods addItem and removeItem on the parent entity, which will keep track of the position (or the methods MoveUp and MoveDown as you suggest).