Cross-table validation in ASP .NET MVC - asp.net-mvc-2

I'm peforming validation using DataAnnotations and Validation Attributes. I'm using ADO NET Entity Model, Domain Services, RIA Services, Silverlight and my projet has a server side that's in ASP .NET.
I want to perform cross-table validation, how can I access the Entity tables from the CustomValidation method.
Let explain with an example.
Suppose I want to avoid two equally named Companies in my data.
(I'm editing the question because I don't know how to response to added comments.
IT'S NOT WHAT I NEED ACTUALLY, I JUST WANT TO ACCESS DATA FROM THE CUSTOM VALIDATION METHOD THAT IS LOCATED IN THE SERVER SIDE OF MY APPLICATION.)
I decorate:
[CustomValidation(typeof(CustomValidatorType), "CompanyNameValidation")]
public string CustomerName { get; set; }
Then my CustomValidatorType would be:
public static class CustomValidatorType {
public static ValidationResult CompanyNameValidation(string companyName,
ValidationContext validationContext) {
// How can I see if companyName is already present in Customers entity table?
if (*Company name already exists*) {
// How can I access the Customer Entity Table to check the Company Name existence?
return new ValidationResult("Comapny already exists.", new[] { "CustomerName" });
}
else
return ValidationResult.Success;
}
}
Thank you in advance
My best regards
Rafael

Related

How can I prevent EF7 from eagerly fixing up navigation properties?

I have an issue using EF7 in a web application with which I could use some help. I'm currently using EF7 RC1.
Here are some models that illustrate my problem.
Contact
public class Contact
{
public Guid Id { get; set; }
public string Desc { get; set; }
public ContactType ContactType { get; set; }
}
ContactType
public class ContactType
{
public Guid Id { get; set; }
public string Desc { get; set; }
public ICollection<Contact> Contacts { get; set; }
}
These models are related via Fluent API like this:
modelBuilder.Entity<Contact>(entity => {
// abridged for clarity
entity
.HasOne(c => c.ContactType)
.WithMany(ct => ct.Contacts)
.IsRequired();
});
My needs are to be able to retrieve a collection of Contact entities from the database with their ContactType property loaded. EF makes this quite easy:
using(var context = new MyDbContext()) {
var contacts = await context
.Contacts
.Include(c => c.ContactTypes)
.Where(/* some search criteria */)
.ToListAsync();
}
The issue is that in loading the ContactType properties of the Contact entities (which happens due to the call to .Include() in the query), EF also helpfully loads the Contacts property of each ContactType entity, resulting in an infinite chain of Contacts pointing at ContactTypes and ContactTypes pointing at Contacts. I understand why this is the default behavior and that it's helpful in many cases, but my needs are to serialize these entities to JSON and send them down to the client - it's a read-only situation.
My desired behavior is for EF to return a collection of Contacts with loaded (non-null) ContactType properties that have their Contacts property set to null. Is this something EF can do? Is there any way to end up with the object graph I want short of manually nulling out properties I don't want populated?
Things I've tried:
Appending .AsNoTracking() to the EF query (which doesn't seem to stop
the Contacts property of the ContactType entity from being loaded)
Telling Json.NET not to serialize infinite reference loops (which is
required to avoid infinite recursion during serialization, but still
results in a lot of extra data being serialized)
You can't avoid EF to load ContactType.Contacts collection, as it's not actually loading it but filling the collection with the loaded Contact instances.
This is why using AsNoTracking has no efect, because is not a problem of lazy loading nor ChangeTracker.
You have three possible solutions:
Use Json.NET ReferenceLoopHandling = ReferenceLoopHandling.Ignore, but as you stated it will generate lot of unnecesary data, as you will get the collection of Contacts for every ContactType
Use [JsonIgnore] attribute on ContactType.Contacts so it will be ignored by the serializer. But it will ignore it always, I don't know if you need it in other situations
Define a DTO, use something like Automapper to map your data in it (without Contacts collection) and serialize it
I would prefer the 3rd option as I don't like sending domain model objects to the client, and it avoid adding attributes to domain model not related with domain.
I have same question Entity Framework 7 Core disable auto loading
I add AsNoTracking()
IQueryable<ScheduleModel> q = _db.Schedules;
q = q.AsNoTracking();
q = q.Include(x => x.ElementItem);
q = q.Include(x => x.ScheduleHours);
Properties not populate automatic now.

EF Code First validating and updating objects

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.

Entity Framework: alternatives to using MultipleActiveResultSets

I'm using ASP.NET WebAPI and ran into a problem with a nested model that should be communicated via a WebAPI Controller:
The entities "bond, stock etc." each have a list of entities "price". Server-side, I use the following class to match this requirement..
public class Bond : BaseAsset
{
public int ID { get; set; }
public string Name { get; set; }
public virtual List<Price> Prices { get; set; }
}
This leads to the table "Price" having a column for bond, stock etc. and, in case a price is attached to a bond, an entry in its column for bond foreign key.
The error I initially got was
There is already an open DataReader associated with this Command
I fixed that by altering the Connection String to allow MultipleActiveResultSets.
However, I feel there must be better options or at least alternatives when handling nested models. Is it, e.g., a sign for bad model design when one runs into such a problem? Would eager loading change anything?
One alternative to mars is to disable lazy loading
In your DbContext
Configuration.LazyLoadingEnabled = false;
plus when you are loading your data you can explicit load your child tables
context.Bonds.Include(b => b.Prices)

Paging and sorting Entity Framework on a field from Partial Class

I have a GridView which needs to page and sort data which comes from a collection of Customer objects.
Unfortunately my customer information is stored separately...the customer information is stored as a Customer ID in my database, and the Customer Name in a separate DLL.
I retrieve the ID from the database using Entity Framework, and the name from the external DLL through a partial class.
I am getting the ID from my database as follows:
public class DAL
{
public IEnumberable<Customer> GetCustomers()
{
Entities entities = new Entities();
var customers = (from c in entities.Customers
select c);
//CustomerID is a field in the Customer table
return customers;
}
}
I have then created a partial class, which retrieves the data from the DLL:
public partial class Customer
{
private string name;
public string Name
{
if (name==null)
{
DLLManager manager = new DLLManager();
name= manager.GetName(CustomerID);
}
return name;
}
}
In my business layer I can then call something like:
public class BLL
{
public List<Customer> GetCustomers()
{
DAL customersDAL = new DAL();
var customers = customersDAL.GetCustomers();
return customers.ToList();
}
}
...and this gives me a collection of Customers with ID and Name.
My problem is that I wish to page and sort by Customer Name, which as we have seen, is populated from a DLL. This means I cannot page and sort in the database, which is my preferred solution. I am therefore assuming I am going to have to call of the database records into memory, and perform paging and sorting at this level.
My question is - what is the best way to page and sort an in-memory collection. Can I do this with my List in the BLL above? I assume the List would then need to be stored in Session.
I am interested in people's thoughts on the best way to page and sort a field that does not come from the database in an Entity Framework scenario.
Very grateful for any help!
Mart
p.s. This question is a development of this post here:
GridView sorting and paging Entity Framework with calculated field
The only difference here is that I am now using a partial class, and hopefully this post is a little clearer.
Yes, you can page and sort within you list in the BLL. As long as its fast enough I wouldn't care to much about caching something in the session. An other way would be to extend your database with the data from you DLL.
I posted this question slightly differently on a different forum, and got the following solution.
Basically I return the data as an IQueryable from the DAL which has already been forced to execute using ToList(). This means that I am running my sorting and paging against an object which consists of data from the DB and DLL. This also allows Scott's dynamic sorting to take place.
The BLL then performs OrderBy(), Skip() and Take() on the returned IQueryable and then returns this as a List to my GridView.
It works fine, but I am slightly bemused that we are perfoming IQueryable to List to IQueryable to List again.
1) Get the results from the database as an IQueryable:
public class DAL
{
public IQueryable<Customer> GetCustomers()
{
Entities entities = new Entities();
var customers = (from c in entities.Customers
select c);
//CustomerID is a field in the Customer table
return customers.ToList().AsQueryable();
}
}
2) Pull the results into my business layer:
public class BLL
{
public List<Customer> GetCustomers(intint startRowIndex, int maximumRows, string sortParameter)
{
DAL customersDAL = new DAL();
return customersDAL.GetCustomers().OrderBy(sortParameter).Skip(startRowIndex).Take(maximumRows).ToList();
}
}
Here is the link to the other thread.
http://forums.asp.net/p/1976270/5655727.aspx?Paging+and+sorting+Entity+Framework+on+a+field+from+Partial+Class
Hope this helps others!

Create an Updatable Model - Entity Framework

I just want to know if there's a way on how to create an Updatable model. Right now, I have to create procedures for insert, update, and delete for all of the tables in my model. This is very tedious so I was wondering if there is one way which I could do to resolve this?
I remember before in my previous work that we used to make models and access them (CRUD) without creating procedures. But i'm not really certain now on how it was made.
Thank you!
There are various ways in which you can automate the generation (on the fly or already generated at compile time) of the actual SQL calls to the database to insert, select, update and delete within the Entity Framework.
You can use the ORM tools (e.g. Linq to Entities) to minimise or eliminate the writing of raw SQL. This means you still have to use the correct attributes on your entities and the properties/methods therein and that's a manual process. (Some backgrounding on this MSDN page)
You can allow the framework to automatically generate your entities based on some existing database schema (only possible with SqlServer-type databases) which basically does 90% of the work for you. There may be some cases where you need to override, for example, the default insert SQL with something custom. This is achieved via the Generate Database Wizard (which I think is a part of Visual Studio 2008+).
You can use POCO classes with EF. If you're using 4.1 and above, you can use the DbContext class. To map your model to the table / columns, simply override OnModelCreating in your context class (which inherits from DbContext). Say you have a model called User, a table called Users, and the context class MyContext, the code could be smth like this:
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
}
public class MyContext : DbContext
{
public MyContext() :
base("MyContext")
{
}
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().
.ToTable("Users");
modelBuilder.Entity<User>().
.Property(d => d.UserId)
.HasColumnName("UserId")
modelBuilder.Entity<User>().
.Property(d => d.UserName)
.HasColumnName("UserName");
}
}
To use it, simply add the User instance to your DbSet, then call SaveChanges:
using(MyContext ctx = new MyContext())
{
var u = new User() { UserId = 1, UserName = "A" };
ctx.Users.Add(u);
ctx.SaveChanges();
}