When using code-first EntityFramework, I need one property to be set before the others - how do I specify the order that it calls the property sets, when it is creating the objects from the database?
E.g.
public class Person
{
public string Name { get; set; }
public string Something
{
get { return something; }
set
{
something = value + " for " + Name;
}
}
private string something;
}
In the code above, I need the Name property to already have been set by the time it sets the Something property.
This isn't the actual example - I know there are other ways to achieve that literally, but I'm not after those, just how I can tell EF to set Name before Something.
I am trying to understand the context of your question. I am going to make the assumptions that:
The value passed to the setter is not another calculated property
the value passed to the setter is intended to be stored in the database
If name is updated you would want Something to be updated to reflect the new name?
I think your mistake here is trying to add a derived portion to the value you are looking to store. Calculate the pretty name in another property, or on a get:
UPDATE had an example overriding the get on the Something Property, but removed as I feel it is bad practice.
public class Person
{
public string Name { get; set; }
public string Something { get; set; }
public string getFancySomething {
{ return Something + " for " + Name; }
}
}
Finally - (and here is where I could use some help as I have not run into a situation where I needed to do something like this) my guess is that you do not need to be storing the partially calculated property Something in the way you were attempting, but if you do need to, I think additional detail might help someone provide you with a better answer.
UPDATE 2
As described in my comments - not sure this would work, and it feels very wrong, but you could try something like:
modelBuilder.Entity<Person>().Ignore(x => x.Something);
and then in the setter:
public class Person
{
public string Name {
get { return Name; }
set {
Name = value;
Something = lookup();
}
}
}
Again this will depend on you needs, and would not satisfy any need to pass this value in, and I am not sure this is a great idea.
Related
I have following entities:
abstract class User
{
string Id
string Name
}
class UserA: User
{
string PropA
}
class UserB : User
{
string PropB
}
It is a good solution to have a unique create (post) with a dynamic parameter and instantiate the subclasses according to a property?
[HttpPost]
public IActionResult Create([FromBody]dynamic data)
{
if (data.PROP == null)
{
_context.Users.Add(new UserA(data.PropA));
}
else
{
_context.Users.Add(new UserB(data.PropB));
}
...
Don't use dynamic. I'm actually kind of surprised that works at all. Though there's no indication that you've actually tested this code yet, so perhaps it doesn't. The modelbinder needs to know a concrete type to bind to, so that it can determine how to map the values onto the destination instance. Without strong types, it can't do anything but make everything a string, since that is how it comes in the request body.
Anyways, for something like this, the correct approach is to use a view model. Your view model should contain all the properties for all the various possible derived types. Again, the modelbinder needs these to determine how to map the data from the request body over, so if a property doesn't exist, it will simply discard the associated data.
This is also why you cannot simply use the base class. If this were a normal method, you could do something like:
public IActionResult Create([FromBody]User data)
Then, inside, you could use pattern matching or similar to cast to the correct derived type. This works because ultimately, the object in memory would actually be an instance of something like UserA, and you're simply up-casting it to User. As a result, you can always cast it back to UserA. However, actions are different. What's coming in from the request is not an object instance. The modelbinder serves to create an object instance out of it, by inspecting the parameter it needs to bind to. If that parameter is of type User, then it will fill the properties on User, and discard everything else. As a result, the object in memory is just User, and there's no way to cast to something like UserA - at least in terms of having all the values that were actually posted for an instance of UserA being on the object.
Which brings us back to the view model:
public class UserViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public string PropA { get; set; }
public string PropB { get; set; }
}
Then, have your action accept that as a param:
public IActionResult Create([FromBody]UserViewModel data)
Then, inside:
if (!string.IsNullOrWhiteSpace(data.PropA))
{
// UserA was posted, map data to an instance of UserA
}
Similarly for UserB. If you like, you could also post an explicit "type" along with the data and switch on that to instantiate the right type. It's up to you. To reduce code duplication, you can instantiate the right type, but store it in an variable of type User. Then, if you need to get back at the correct type, you can use pattern matching:
User user;
switch (data.Type)
{
case "UserA":
user = new UserA
{
Id = data.Id,
Name = data.Name,
PropA = data.PropA
};
break;
// etc.
default:
user = new User
{
Id = data.Id,
Name = data.Name
};
break;
}
Then later:
switch (user)
{
case UserA userA:
// do something specific with `userA`
// etc.
}
Or:
if (user is UserA userA)
{
// do something with `userA`
}
I am working on an N-tier application consisting of a UI layer (MVC), a Business Layer, a Domain layer (for the models) and a DAL for repositories and the EF DbContext.
I'm a bit confused about the inner workings of Entity Framework when updating the properties of an existing object and I'm looking for a good way to validate an object before updating its values in the database.
I have the following model:
public class BlogPost
{
public int BlogPostId { get; set; }
[Required]
public String Title { get; set; }
[Required]
public String Description { get; set; }
[Required]
public DateTime DateTime { get; set; }
public byte[] Image { get; set; }
}
I have the following methods in my manager in BL:
public BlogPost AddBlogPost(string title, string description, byte[] image = null)
{
BlogPost blogPost = new BlogPost()
{
Title = title,
Description = description,
DateTime = DateTime.Now
};
Validate(blogPost);
moduleRepository.CreateBlogPost(blogPost);
return blogPost;
}
public BlogPost ChangeBlogPost(BlogPost blogPost)
{
moduleRepository.UpdateBlogPost(blogPost);
return blogPost;
}
And I have the following methods in my DAL:
public BlogPost CreateBlogPost(BlogPost b)
{
b = context.BlogPosts.Add(b);
context.SaveChanges();
return b;
}
public BlogPost UpdateBlogPost(BlogPost b)
{
context.Entry(b).State = EntityState.Modified;
context.SaveChanges();
return b;
}
My question now is: what's a good way to check that the model is valid before actually trying to change its values in the database?
I was thinking something like this:
public BlogPost ChangeBlogPost(BlogPost blogPost)
{
// STEP 1: put the updated data in a new object
BlogPost updatedBlogPost = new BlogPost()
{
Title = blogPost.Title,
Description = blogPost.Description,
Image = blogPost.Image,
DateTime = blogPost.DateTime
};
// STEP 2: check if the model is valid
this.Validate(updatedBlogPost);
// STEP 3: read the existing blog post with that ID and change the properties
BlogPost b = moduleRepository.ReadBlogPost(blogPost.BlogPostId);
b.Title = blogPost.Title;
b.Description = blogPost.Description;
b.Image = blogPost.Image;
b.DateTime = blogPost.DateTime;
moduleRepository.UpdateBlogPost(blogPost);
return blogPost;
}
EDIT: I figured it's maybe better to just accept primitive types as parameter in the above method instead of the object.
I have a feeling that's too much work for a simple update, but I couldn't find anything else on the internet.
It's probably also worth noting that I'm using a singleton for the DbContext so I have to make sure Entity Framework doesn't change the values in the database before checking that those values are valid (since another call to the context by another class can cause SaveChanges()).
I know singleton on a DbContext is bad practice, but I saw no other option to avoid countless exceptions when working with multiple repositories and entities being tracked by multiple context instances.
PS: I also read about change tracking in Entity Framework but I'm not 100% sure how this will affect what I'm trying to do.
All suggestions and explanations are welcome.
Thanks in advance.
You would check ModelState.IsValid. There are a lot of validation mechanisms built into MVC that you can take advantage of. Built in attributes such as [Required] that you reference above, custom validators, making your business class implement IValidatableObject, overriding EF SaveChanges() to name a few. This article is a good start: https://msdn.microsoft.com/en-us/data/gg193959.aspx
Ok so I kinda answered my own question while doing some research and testing with some dummy data. I thought that when a property changed in MVC as a result of an Edit view, EF also tracked it and changed it in the database.
I figured out that's not how model binding works and realized after some fooling around that model binding actually creates a new object (instead of editing the properties of a dynamic proxy).
I guess I can now just validate the model and then just update the one with the same primary key in the database.
What's the best way to set default properties for new entities in DDD? Also, what's the best way to set default states for complex properties (eg. collections)?
My feeling is that default values should be in the models themselves as they are a form of business rule ("by default, we want X's to be Y & Z"), and the domain represents the business. With this approach, maybe a static "GetNew()" method on the model itself would work:
public class Person {
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public bool IsAlive { get; set; }
public List Limbs { get; set; }
public static Person GetNew() {
return new Person() {
IsAlive = true,
Limbs = new List() { RightArm, LeftArm, RightLeg, LeftLeg }
}
}
}
Unfortunately in our case, we need the collection property to be set to all members of another list, and as this model is decoupled from its Repository/DbContext it doesn't have any way of loading them all.
Crappy solution would be to pass as parameter :
public static Person GetNew(List<Limb> allLimbs) {
return new Person() {
IsAlive = true,
Limbs = allLimbs
}
}
Alternatively is there some better way of setting default values for simple & complex model properties?
This is an instance of the factory pattern in DDD. It can either be a dedicated class, such as PersonFactory, or a static method, as in your example. I prefer the static method because I see no need to create a whole new class.
As far as initializing the collection, the GetNew method with the collection as a parameter is something I would go with. It states an important constraint - to create a new person entity you need that collection. The collection instance would be provided by an application service hosting the specific use case where it is needed. More generally, default values could be stored in the database, in which case the application service would call out to a repository to obtain the required values.
Take a look at the Static Builder in Joshua Bloch's Effective Java (Second Edition). In there, you have a static builder class and you chain calls to set properties before construction so it solves the problem of either having a constructor that takes a ton of arguments or having to put setters on every property (in which case, you effectively have a Struct).
Oftentimes I need to return a list of two or three columns from a stored proc in the data layer. I usually use entities to push data back to the business/UI layer. However, I don't want to create an entity for something that is not really an entity.
Lets say I have to return a set of "date, string, string", is there any other way to do this.. for two columns, i can perhaps get away with a dictionary. I always end up creating a dummy entity but thought I'll ask this time.
Create a new model to store the data:
public class ResultModel
{
public DateTime DateTime1 { get; set; }
public string String1 { get; set; }
public string String1 { get; set; }
}
then just store your data into this like so:
IEnumerable<ResultModel> results =
Entities.Table.Select(r => new ResultModel
{
DateTime1 = r.DateTime,
String1 = r.String1,
String2 = r.String2
});
Not verified the code but is a guide as to how to achieve this.
You could probably use a Tuple for this kind of data however I've never found any real detriment to creating more understandable types, even for simple data.
My task is to change the ErrorMessage property of the DataAnnotation validation attribute in MVC2.0. For example I should be able to pass an ID instead of the actual error message for the Model property and use that ID to retrieve some content(error message) from a another service e.g database, and display that error message in the View instead of the ID. In order to do this I need to set the DataAnnotation validation attribute’s ErrorMessage property.
[StringLength(2, ErrorMessage = "EmailContentID.")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
It seems like an easy task by just overriding the DataAnnotationsModelValidatorProvider ‘s
protected override IEnumerable GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable attributes)
However it seems to be a complicated enough.
a. MVC DatannotationsModelValidator’s ErrorMessage property is read only. So I cannot set anything here
b. System.ComponentModel.DataAnnotationErrorMessage property(get and set) which is already set in MVC DatannotationsModelValidator so we cannot set again. If you try to set you get “The property cannot set more than once…” error message appears.
public class CustomDataAnnotationProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
IEnumerable<ModelValidator> validators = base.GetValidators(metadata, context, attributes);
foreach (ValidationAttribute validator in validators.OfType<ValidationAttribute>())
{
messageId = validator.ErrorMessage;
validator.ErrorMessage = "Error string from DB And" + messageId ;
}
//......
}
}
Can anyone please help me on this?
Here is the question: What is your motivation to changing the error message property?
Think this through very carefully, as you are heading down a path where you are obfuscating what is actually happening in the application. Certainly the database informatino is useful, but it is not really part of the validation, nor should it be.
When you head in this direction, you are essentially saying that the validation can only be invalid if there is a database problem. I see two issues with this:
It breaks the separation of concerns. You are reporting a persistance error in the model, which is not where it occurred.
The solution is not unit testable, as you must engage the database.
I don't like either of the two above.
Can you solve this? Possibly if you will create your own custom validation attribute. I would have to check and ensure that is correct. Another option is to aim for custom validation:
http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
This article can also help you head in the direction you desire:
http://ryanrivest.com/blog/archive/2010/01/15/reusable-validation-error-message-resource-strings-for-dataannotations.aspx
Do you want to solve this? Not really if you are attempting to keep a proper separation of concerns in your application. I would not polute my validation error message (this is not valid) with a database error (I am not valid, but the database also blew up). Just my two cents.
There are built in ways to get the error message via a resource. Instead of a database lookup to get a resource at runtime, generate resources from your database and use that for your error messages.
You can then use the ErrorMessageResourceName and ErrorMessageResourceType to allow the DataAnnotation to perform a resource lookup instead of hard-coding a specific string.
public sealed class MyModel
{
[Required(
ErrorMessageResourceName="MyDescriptionResource",
ErrorMessageResourceType=typeof(MyCustomResource))]
public string Description { get; set; }
}
Also you may want to have a look at ValidationAttribute.FormatErrorMessage Method on msdn.
This method formats an error message
by using the ErrorMessageString
property. This method appends the name
of the data field that triggered the
error to the formatted error message.
You can customize how the error
message is formatted by creating a
derived class that overrides this
method.
A quick sample (and not meant to be a definitive example)
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false,
Inherited = true)]
public sealed class PostCodeValidationAttribute
: ValidationAttribute
{
public override bool IsValid(object value)
{
if( value == null )
return true;
string postCode = value as string;
if( string.IsNullOrEmpty(postCode) )
return true;
if ( !PostCode.IsValidPostCode(postCode, this.PostCodeStyle) )
return false;
return true;
}
public PostCodeStyle PostCodeStyle { get; set; }
public override string FormatErrorMessage(string name)
{
return string.Format(
"{0} is not a valid postcode for {1}", name, PostCodeStyle);
}
}
* I've omitted the PostCodeStyle enumeration as well as the PostCode class for validating a postcode.