EF Code First 4.1: how to map Member.UserId to the aspnet_Users.UserId? - asp.net-mvc

I have a Member class:
public class Member
{
// key
public Guid UserId { get; set; }
// some other fields
}
Also I have a aspnet_Users table with has UserId primary column.
We can:
1). Add additional property MembershipUser to the Member object and get it's value by calling Membership.GetUser(this.UserId) method.
Also I've add
context.Database.ExecuteSqlCommand("ALTER TABLE [dbo].[Members] WITH CHECK ADD CONSTRAINT [FK_Members_aspnet_Users] FOREIGN KEY([UserId]) REFERENCES [dbo].[aspnet_Users] ([UserId])");
to the DataContext.Seed() method to ensure that Member can not be added without aspnet_Users account.
2). Use fluent API in OnModelCreating. If this a good case how to map them correctly?
What's the best choice? Any thoughts?

No matter how I tried to avoid it, I've found the best approach is to implement my own MembershipProvider and have it use my model, rather than trying to shoehorn my model into the built-in membership provider.
If you are going down the other route you have to map the ASP.NET Membership tables to your domain and derive your Member class from the ASP_User class (or vice versa if you want to ensure that all Users you create are Members). In the end, I've discovered that although it seems like more effort up front, implementing MembershipProvider is the easier approach.

You don't. Don't add foreign key constraints against the aspnet_* tables. It's a recipe for trouble. Membership is plug-in type system, and you have to treat it as a black box.
Simply lookup the data in your tables with the MembershipUser.ProviderUserKey as it's value. Something like this:
from m in Member where UserID == (Guid)Membership.GetUser().ProviderUserKey select t;

Related

NHibernate mapping class with attribute of same type

I am new to the .NET MVC. However this "problem" I am stuck at looks pretty common, I cannot find any tutorial or stackoverflow thread that explains how to do it properly.
I have a class, MyClass which has two attributes of same type
public class MyClass : IEquatable<MyClass>
{
public virtual MyClass LeftChild { get; set; }
public virtual MyClass RightChild { get; set; }
...
}
Now I have problem with nhibernate mapping. At first I tried one-to-one mapping. I created new instance and DO NOT set Childs , persisted it (lets say Id=1), and pass this instance to View and I expected that RightChild will be NULL and LeftChild will be NULL. But in the debbug mode i can see, that the RightChild was set to MyClass with Id=1 (Like MyClass instance set itself to this attribute) and same with LeftChild.
Mapping MyClass.hbm.xml
...
<one-to-one name="LeftChild" class="MyClass"/>
<one-to-one name="RightChild" class="MyClass"/>
...
Is it right approach to do it with one-to-one or I should use something else ?
References, where our table contains foreign keys, are almost always best to map with many-to-one.
Simply think about it as a standard reference to other instance (Country, Currency)... which is accidentally of a same type.
<many-to-one name="LeftChild" column="LeftChild_ID" class="MyClass"/>
<many-to-one name="RightChild" column="RightChild_ID" class="MyClass"/>
The only challenge I see, is to be sure that the server part (C# code, app) will be properly setting these values. There is not bi-directional mapping in this kind of persisted information. Each sibling, needs its own information who is right who is left.
I mean, comparing with Similar mapping: parent-child (also same type). In that case we would have child having reference to parent, and parent having collection of children.
But that is not the same here.. again.. we map just one side of the relation.
A one-to-one is not suitable here, because it requires two tables, with (almost) the same amount of rows, sharing same column as a key... I like to use it, but for kind of Additional info... see:
NHibernate Dynamic Columns Number
NHibernate Optional Join generates insert instead of update

How to map auto increment Id from domain model to entity model in Entity Framework ASP.NET Web API

I am trying to follow DDD for my current project. My question is specifically regarding POST request that contains values for my domain model. To simplify, let's say following is my domain model:
class Person
{
public int Id {get, set};
public string name {get, set};
}
And below is the entity model backing above domain:
class PersonEF
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get, set};
public string name {get, set};
}
Now when I receive a POST request to create a new Person it doesn't contain the Id as it's supposed to be generated by the database. I first map Person to PersonEF using AutoMapper which sets the Id to 0 in PersonEF and hence the INSERT in database fails. So to fix these my options are:
Name Id as something else in Person. If I do this then I would have to write custom mapping just for Id for GET requests.
Make Id nullable (int?) in both Person and PersonEF and this way auto increment will work, but having key as nullable int doesn't sound like a good idea in itself.
So please suggest the best way to do this.
EDIT
My bad. Code was missing context.SaveOrUpdate(). I added that and it's working as expected.
It's hard to say for sure, as the code of most importance, that you should have posted, would be that of your controller action where the mapping and saving occurs. However, I can tell you that the 0 is the default value for an int. This is not due to AutoMapper, or mapping in general, per se. The entity, freshly created, without any other interaction, would still have 0 as the id.
As a result, this should not be causing a problem with saving the entity, or else you'd never be able to save any entity that had an int PK. However, depending on what Entity Framework thinks you're trying to do with the entity, it might cause problems. Namely, you need to make sure that Entity Framework is aware that you're wanting to create this entity and not just update it. Usually, that's achieved by simply adding it to the DbSet:
db.PersonEFs.Add(personEF);
Not sure why you would need to go any farther than that, but if that's not working for some reason, you can be a bit more explicit:
db.Entry(personEF).State = EntityState.Added;
However, really, if you need to do that, there's something else going on that you'd just be masking.

Entity Framework 4.1 - Code First with existing Database, how to define classes, using Attributes or EntityTypeConfiguration? What is the difference?

I have been studying the EF for a short time and cant find the answer to this question.
I have existing database and I am using CodeFirst to create classes for the model.
What is the difference in using Attributes and EntityTypeConfiguration to define parameters of table columns?
Since the database already has defined foreign keys and unique constraints, and so on, how and where to implement the validation for a best and most fluid result for use in ASP.NET MVC3?
Is it better to implement Attributes and CustomValidation or to use TryCatch blocks to catch errors from db?
Does Validator.TryValidateObject(myModelObject, context, results, true); use validation rules defined only as Attributes or can it use rules defined in EntityTypeConfiguration?
Thank You
Get the Entity Framework Power Tools CTP1 and it will reverse engineer your database and create entities, and a full data mapping. This is different than Model or Database first in that it generates a fluent model rather than using an .edmx file. You can see exactly how it works then.
See the following article about how you can create your entity classes from existing database :
http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-model-amp-database-first-walkthrough.aspx
Code generation templates will do the work for you, you don't need to write them if you have an existing db.
For validation, you can create new partial classes under the same namespace and put DataAnottations for your properties. Here is an example for you :
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
namespace TugberkUgurlu.App1.DataAccess.SqlServer {
[MetadataType(typeof(Country.MetaData))]
public partial class Country {
private class MetaData {
[Required]
[StringLength(50)]
[DisplayName("Name of Country")]
public string CountryName { get; set; }
[Required]
[StringLength(5)]
[DisplayName("ISO 3166 Code of Country")]
public string CountryISO3166Code { get; set; }
[DisplayName("Is Country Approved?")]
public string IsApproved { get; set; }
}
}
}
-Since the database already has defined foreign keys and unique constraints, and so on, how and where to implement the validation for a best and most fluid result for use in ASP.NET MVC3?
These should happen via your generated model. Keys are automatically inferred. If you reverse engineer an existing database the attributes will be created for you. If not, there are basic rules that are followed. The entity framework will attempt to use an auto incrementing primary key for example unless you tell it otherwise via
[DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]
The relationships are already part of your model so there is your referential integrity, and the data annotations will define the validation rules.
-Is it better to implement Attributes and CustomValidation or to use TryCatch blocks to catch errors from db?
Implement attributes. Define your metadata classes with your attributes in them.
In addition you want to catch any db errors for anything else that is unexpected if your db has additional logic in there not defined in your model (try catch at some level should generally be used anyways for logging purposes_
-Does Validator.TryValidateObject(myModelObject, context, results, true); use validation rules defined only as Attributes or can it use rules defined in EntityTypeConfiguration?
As far as I'm aware only the attributes are used. I'm going to try to test this later though as I'd like a definite answer on this as well :)

Incorporate Membership in ASP.NET MVC

I have been wondering on how to use ASP.NET Membership together with MVC. The basic setup is very simple, but if I want to use extra fields like address, nickname etc, should I then use ProfileCommon or should I create a separate table which contains the extra data and link to the UserId in Aspnet_users?
I have an issue where I have changed the name in Membership to use the email, and I then need the extra fields (address, nickname etc.). If I use ProfileCommon I can receive the object by
public static ProfileCommon GetProfile(string username)
{
return ((ProfileCommon)(ProfileBase.Create(username)));
}
The problem is I save the UserId in different tables, and I can't figure out how to receive the ProfileCommon object by UserId instead of username (which in my case is the email)?
I could then either change the relation in the different tables to use the email, but this would be a very slow implementation, or I could create a separate table with the extra fields.
Is there perhaps a third and better option?
You could simply join the user table in order to receive the email.
Generally it does not seem to be a good idea to use two different fields as the id.
I chose to create the separate table, since I would not be limited by the ProfileBase class.

Field in mapped entity required

I'm not sure if my problem is solvable in a more or less comfortable way.
There is a class Person which has mapped 'hasOne' a participant.
The person has a birthday but this field is not required on the person itself. But if I would like to add a participant to the person then the birthday is required.
How to get rid of this
move the birthday information to the participant object -> That's how I did it for now, but I think moving person related information to other objects cannot be the final solution
Map the property in both classes -> how to tell the validator when it's required and when not?
Merge the two objects -> for now not allowed
Maybe someone has a better idea, I use the nHibernate Validator and there I configure the validation in the class (where the information 'birthday' is not a property on both - maybe this would be a solution?)
With NHibernate validator attributes as you mentioned. This would be in the Participant class. Would this work for you? It is optional on the base class and nullable as you see (can't change type on overriding)
[NotNull, NotEmpty]
public override DateTime? Birthday { get; set; }
This would still leave field nullable in the DB, but don't see way around this without having a table per class implementation rather than a class per hierarchy fluent implementation. Your domain validation will be there to protect though.

Resources