In my User class I have the password which is SecureString. To save the password, I have added the UserPassword property.
Sample code:
internal partial class User
{
public string ID { get; set; }
private string _password;
public SecureString Password
{
set { _password = SomePasswordHashing(value.ToString); }
}
public string UserPassword
{
get { return _password; }
set { _password = value; }
}
}
For the saving/retrieving of the UserPassword, does this property need to be public?
Is there a way not to load a UserPassword property (for instance when searching for the users, I would want to exclude loading all users' passwords)?
For the saving/retrieving of the UserPassword, does this property need
to be public?
Yes. EF-Code first needs properties to be public.
Is there a way not to load a UserPassword property (for instance when
searching for the users, I would want to exclude loading all users'
passwords)?
You can transform the results when searching to exclude passwords
var users = db.Users.Where(/* */).Select(u => new User{Name = u.Name});
Or use a DTO class which does not have a password property and return the DTO classes instead of the model object.
Related
I have create a class, let's call it User. In this class I have a custom created class called EMail. This class contains only a string that holds the value of the emailadress and some logic to verify the address. So it looks like this in my User class.
public class User{
public string Name{get;set;}
public EMailAddress EMail{get;set;}
...
}
I now want to bind this EMail to a column in my databas by using EF4's CTP5 code. But I can't do this, I don't even get an good exception back, all I get is "Thread aborted exception", but if I comment out my EMail property it works good.
My EMailAddress class looks like this.
public class EMailAddress
{
//-- Declaration
private string _email;
//-- Constructor
public EMailAddress(string emailAddress)
{
if (emailAddress == null)
throw new ArgumentNullException(string.Format("Supplied emailaddress can't be null"));
if (!IsValid(emailAddress))
throw new ArgumentException(string.Format("'{0}' is not a valid Emailaddress", emailAddress));
_email = emailAddress;
}
//-- Methods
private static bool IsValid(string emailAddress)
{
Regex re = new Regex(Constants.EMAIL_REGULAR_EXPRESSION_PATTERN);
return re.IsMatch(emailAddress);
}
public override string ToString()
{
return _email;
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (obj is string)
return _email == (string)obj;
if(obj is EMailAddress)
return _email == ((EMailAddress)obj).ToString();
return false;
}
public override int GetHashCode()
{
return _email.GetHashCode();
}
//-- Operator
public static bool operator ==(EMailAddress emailAddress, EMailAddress emailAddress2)
{
return object.Equals(emailAddress, emailAddress2);
}
public static bool operator !=(EMailAddress emailAddress, EMailAddress emailAddress2)
{
return !(emailAddress == emailAddress2);
}
}
And I want to keep my EMailAddress class free of any public properties. Is there a way to let the EF use the .ToString() method when itsaves the value to the database, and use the constructor when loading the data from the database to populate my objects.
Thanks...
No it is not possible. You have two choices:
Add another string property to your User class. This property will be responsible for returning email and setting email (creating EmailAddress instance). This property will be mapped. Add [NotMappedAttribute] to EMail property. You can play with visibility of the new property. In common EF you can change visibility of property but I'm not sure if it is also possible in code-first.
Map EMailAddress as complex type (mark it with [ComplexTypeAttribute] but in such case you again need to add string property to EMailAddress.
You can map non-public properties to columns in EF but the default codefirst API doesn't support it out of the box. I've made some free code available that you can use in your projects to support this need. You'll still have to have the properties but they can be protected or private or internal now.
Details are here
http://blogs.msdn.com/b/schlepticons/archive/2011/08/31/map-private-properties-with-ef-fluent-api.aspx
I have a User class that holds some default data.
public class User : BaseEntity
{
//-- Declaration
private string _firstname;
private string _lastname;
private ICollection<BaseProfile> _profiles = new List<BaseProfile>();
//-- Constructor
public User() { }
//-- Properties
public string Firstname
{
get { return _firstname; }
set { _firstname = value; base.Name = string.Format("{0} {1}", this.Firstname, this.Lastname); }
}
public string Lastname
{
get { return _lastname; }
set { _lastname = value; base.Name = string.Format("{0} {1}", this.Firstname, this.Lastname); }
}
public EMailAddress EmailAddress { get; set; }
public SocialSecurityNumber SocialSecurityNumber { get; set; }
public Password Password { get; set; }
public virtual ICollection<BaseProfile> Profiles { get { return _profiles; } set{_profiles = value; }}
}
The Profiles contains diffrent Profiles data based on diffrent profiles the user can have. If the user is a player, then Profiles will contain of a ProfilePlayer clas, if the user would be a Trainer it will contain a ProfileTrainer class. And if the User is a Player and a Trainer it will contain 2 profiles, one ProfilePlayer Class and one ProfileTrainer class. This profile classes would contain information specified for the diffrent profiles the user could be.
Now to my question, how can I tell the EF that it should save the diffrent BaseProfiles as the specified types, cause when EF is createing the databas for me, it's created as a BaseProfiles even if the "real" type is ProfilePlayer class. Do I need to manually create the diffrent tables and then do some mapping or is there a simple way to tell EF to create the diffrent profilesclasses and to save the baseprofiles data into correct table?
I did find the solution to my problem.
modelBuilder.Entity<Domain.BaseProfile>()
.Map<Domain.Model.ProfilePlayer>(p => p.Requires("Discriminator").HasValue("ProfilePlayer"))
.Map<Domain.Model.ProfileTrainer>(p => p.Requires("Discriminator").HasValue("ProfileTrainer"));
I would like to know if this is possible to create a custom validation for my User Entity.
I Want to verify if the username is unique.
If the user Already exist, I don't want to save it and show a warning.
I Read about Data Annotation inherits but I'm not sure of what I'm doing.
Please help.
Thanks.
Entity-Framework 4
Asp.net MVC 2
Yes it is possible, you can create your own Custom Attribute class and validate the entity. Something similar to this code,
[AttributeUsage(AttributeTargets.Class)]
public class DuplicateUserAttribute : ValidationAttribute
{
private const string _defaultErrorMessage = "user '{0}' Already exist";
public DuplicateUserAttribute ()
: base(_defaultErrorMessage)
{
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString);
}
public override bool IsValid(object value)
{
UserEntity NewUser = value as UserEntity;
//Write here logic to validate the user is already exist in database like
context.UserList.Where(u=>u.Name ==NewUser .UserName)
return ;
}
}
[DuplicateUser]
Class User
{
…
}
Also more on CustomeAttribute
Using EF Code First, how can I interrupt the saving of a field value so I can hash it? A simple example would be a password field:
public class Account
{
private string _password;
public string Password
{
get
{
return _password;
}
set
{
_password = MyHashMethod(value);
}
}
}
This appears to work when saving the value to the database, but doesn't work when retrieving the value.
EDIT:
Changed _password = MyHashMethod(_password) to MyHashMethod(value) above. Same correction needs to be made in the answer below.
I would just make it like:
public class Account {
public string HashedPassword { get; set; }
public string ClearTextPassword {
set { HashedPassword = MyHashMethod(value); }
}
}
Only HashedPassword is stored in DB.
I am learning some good code practice that's why i was going through some code, some thing i could not understand in it. It has made property in a separate class for each entity like in userClass it has property
#region public properties
private int uid;
public int userId
{
get { return uid; }
set { uid = value; }
}
private string uName;
public string userName
{
get { return uName; }
set { uName = value; }
}
private string pwd;
public string password
{
get { return pwd; }
// set { pwd = value; }
}
private string uAddress;
public string userAddress
{
get { return uAddress; }
set { uAddress = value; }
}
private string fName;
public string firstName
{
get { return fName; }
set { fName = value; }
}
private string lName;
public string lastName
{
get { return lName; }
set { lName = value; }
}
private string uPhone;
public string userPhone
{
get { return uPhone; }
set { uPhone = value; }
}
private string uMobile;
public string userMobile
{
get { return uMobile; }
set { uMobile = value; }
}
private int secretQuestion;
public int securityQuestion
{
get { return secretQuestion; }
set { secretQuestion = value; }
}
private string userAnswer;
public string answer
{
get { return userAnswer; }
set { userAnswer = value; }
}
#endregion
and from the business logic class it uses the property instead of using directly any entity's attribute name, but i am confuse whats there need to make a property like this?
other then this it has got enums for database column name which has a clear reason behind this that if in near future we have to change the database table's fields name then we don't have to change through out the whole business logic class and we can make changes to enum directly, But what is there use of creating property like this please elaborate me on this
Are you really asking why it uses properties instead of having public fields?
Fields are an implementation detail - they're how data is stored, which shouldn't be something the outside world cares about, at least for 99% of types. Properties are part of the contract that a type has in terms of its API - the implementation is up to the type. In other words, it's a matter of encapsulation. Properties can be expressed in interfaces, as abstract methods etc, precisely because they keep the contract and the implementation separate.
Additionally, properties make databinding, debugging and various other things simpler. I have an article about why properties matter, which you may find useful.
Having said all of this, those properties are implemented in a tedious way - and they don't obey .NET naming conventions. I would have written them as:
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
// etc
Properties can be defined on Interfaces, but member fields cannot. So if you needed to refactor this class to a class that implements an interface, you can put the properties on the interface (and then have other classes that implement them as well.)
Some similar questions:
Public Fields versus Automatic Properties
Property vs public field.
In additional to above: Actually you can easily decide public field or property by yourself. It is quite easier to understand that:
(1) Name is a property of class Person
(2) Speed is a property of class Plane
(3) Empty is a public field of class String. If you say String has a property named Empty, it's really weird. And String has a property Length is easy to understand.