locked
Unique name validation RRS feed

  • Question

  • User1581150968 posted

    Requirements
    Customer has products. Product has a name. Product name must be unique per customer. How...

    Technology

    Using Microsoft ADO Entities with ASP.NET Dynamic Data. These use Entity data sources and detail views.

    Fail #1 – Add  partial void OnNameChanging(string value) to partial class Customers. Problem is that the customer link hasn’t been set yet

    Fail #2 - Add to context_SavingChanges on the Context. This will run every time the context saves and also the error isn't given to the corrrect UI field.

    Fail #3 - Add a FieldTemplate called UniqueText_Edit.ascx. No easy way to know when the object is being added or updated.

    Fail #4 - Leave the exception. Page just crashes

    Fail #5 - Add Inserting on the DataSource and/or the DetailsView. No nice way set the validation error on the correct field.

    If we had used LINQ to SQL, would the OnValidate method help. Why has this been left out of Entities?

    - All we want to do is mark a field as unique in the domain (with a ValidationAttribute?) and then the Field Template control pick up the error message.

    Comments/Questions welcome.

    mike
     

    Thursday, October 16, 2008 12:00 PM

All replies

  • User-1005219520 posted

    Mike,

    A unique constraint is a pure DB side constraint. Unless you are generating a GUID, you can't check this constraint on the client side (even with a GUID you can't check on the client side but you are statistically guaranteed a unique value). Most membership forums require each user to have a unique name (just like your product name). They solve this server side problem with a special post back "Check User Name".

    >>If we had used LINQ to SQL, would the OnValidate method help. Why has this been left out of Entities?

    OnValidate in L2S is a client side validation and would not help.  OnValidate in L2S is used to validate any field in an entity (when specific field change methods won't work). In EF you use OnSavingChanges. See Customizing Validation for All Data Fields by Using a Partial-Class Method in the ADO.NET Entity Framework  in How to: Customize Data Field Validation in the Data Model

     >>All we want to do is mark a field as unique in the domain (with a ValidationAttribute?) and then the Field Template control pick up the error message

    Validation occurs on the client side with client side info. Your problem doesn't fit into this paradigm. You will need to either trap the server side exception (which probably means you need to set 

    EnablePartialRendering="false"

     or use a special postback to test the candidate key.

    Thursday, October 16, 2008 2:30 PM
  • User-797310475 posted

    Fail #3 - Add a FieldTemplate called UniqueText_Edit.ascx. No easy way to know when the object is being added or updated.

    Actually, you should be able to detecte the difference by looking at the Mode property of the FieldTemplateUserControl class. If it's equal to Edit, then you could enable a CustomValidator that would do the querying to figure out if the value of that column already exists in the DB. I don't have any code handy, but it would be possible to do this using a generic LINQ expression that should work for any column.

    Thursday, October 16, 2008 9:19 PM
  • User-330204900 posted

    Hi Mike, this is how i did something similar: 

    //Business Logic example
    public partial class NorthwindDataContext : System.Data.Linq.DataContext
    {
    	partial void InsertCustomer(Customer instance)
    	{
    		var NWDC = new NorthwindDataContext();
    		if (NWDC.Customers.SingleOrDefault(c => c.CustomerID == instance.CustomerID) != null)
    		{
    			throw new ValidationException("Duplicate CustoemrID is not allowed");
    		}
    		else
    		{
    			// finally send this to the DB
    			this.ExecuteDynamicInsert(instance);
    		}
    	}
    }

     

    But I'm not sure how to do this in EF. EF does not seem as flexible as L2S

    Hope this helps [:D]

    Friday, October 17, 2008 2:44 AM
  • User1581150968 posted

    Thanks for the responses.

    ricka6, Where can I add the try catch?. I've added the unique key on the database but want to make sure the ASP.NET works well for for the user. How can I make sure the exception is handled? What does EnablePartialRendering="false"  get me?

    marcind, So Copy Text_Edit.ascx (UniqueNameForCustomer_Edit.asx) and UIHint. Add a CustomValidator....  

    protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
    {
        foreach (Product product in ContextFactory.Context.Products)
        {
            // How can we skip edits?
            if (this.Id == product.Id)
                continue;
    
            // Hard coding of Customer (I guess this is ok for our template)
            if (TextBox1.ToUpperInvariant() == product.Name.ToUpperInvariant()
                && this.CustomerReference.EntityKey == product.CustomerReference.EntityKey)
            {
                args.IsValid = false;
                return;
            }
        }
    }
    a) How can we skip if we are Editing?
    b) How do i get back to the Customer Reference. Should this be part of the for loop?
    sjnaughton Looks like linq2sql can do this. Did Microsoft miss out the OnValidate by mistake or is it "by design"!?
    Thanks again.
    m
    Friday, October 17, 2008 4:37 AM
  • Friday, October 17, 2008 5:30 PM
  • User1581150968 posted

    sjnaughton Thanks for the reply. These are both covered by Fail #1 and #2.

    Adding the validation to the property doesn't give me the customer id that has been set. I think that is why Linq2Sql has OnValidate

    Adding the validation to the save means that the unique name check will be performed on EVERY save. This sounds very inefficient

    Am I missing something or is this just another shiny Microsoft technology that could do with a service pack?

    Cheers, Mike.

    Monday, October 20, 2008 4:42 AM