Mar 23, 2010

The "OnDelete" property of navigation in Entity Framework

This property affects the the behavior of entity framework when delete an entity. Here are two scenario.

[Fact]
        public void can_delete_order_with_lines_loaded()
        {
            TestEntities db = new TestEntities();
            Order o1 = db.Orders.Include("OrderLines").First();
            db.DeleteObject(o1);
            db.SaveChanges();

        }

        [Fact]
        public void can_delete_order_with_no_lines_loaded()
        {
            TestEntities db = new TestEntities();
            Order o1 = db.Orders.First();
            db.DeleteObject(o1);
            db.SaveChanges();

        }

If the values of OnDelete is Cascade, in the first case, because ef knows there are orderlines of the order, because they are loaded in memory, so it will delete the children (orderlies) first, then delete the order. In the second case, because the ef think that order has no child, because there is no children in memory, so it will just delete the order.

If the values of OnDelete is "None", in the first case, it will throw exception like "System.InvalidOperationException : The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.". Because, ef knows that it has children in memory, it can not delete them unless you manually delete the children first. In the second case, because there is no children in memory, ef will just delete the order.

Please note that ef does not consider the foreign key property between tables in database, when it do the above operations. So if the above behavior is just delete the parent, but in database there is no such cascade for the foreign key, it will failed as well. But the values of navigation does affect the database generation script if you choose to generate database from the model. If it is cascade, it will generate a foreign key with cascade, if not it will generate a foreign key with no cascade. But this is design time behavior, but not runtime behavior

Mar 8, 2010

jQuery.globalEval

$.globalEval utility is a useful function, because it is preferred compare with eval in calling ajax script. What it does is adding script tag to document, then remove it later.

globalEval: function( data ) {
 if ( data && rnotwhite.test(data) ) {
  // Inspired by code by Andrea Giammarchi
  // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
  var head = document.getElementsByTagName("head")[0] || document.documentElement,
   script = document.createElement("script");

  script.type = "text/javascript";

  if ( jQuery.support.scriptEval ) {
   script.appendChild( document.createTextNode( data ) );
  } else {
   script.text = data;
  }

  // Use insertBefore instead of appendChild to circumvent an IE6 bug.
  // This arises when a base node is used (#2709).
  head.insertBefore( script, head.firstChild );
  head.removeChild( script );
 }
},

$.globalEval("document.write('<h1>hello</h1>');");

Mar 7, 2010

jQuery event binding internal

The event binding in jQuery is very interesting. It is designed with several goals. 1. It should works consistently across browsers. 2. It should allows attaching more than one handler function to a event. The event registration information is saved in a jQuery.data(elem). In jQuery.cache actual data store for all these data. A piece of data in the cache can be assigned to the element. Below is some pesudo code to demonstrate the data structure

function fn(..){..}
fn.guid = ..

handleObject = { data: ..,
                 guiid: ..,
                 namespace: "..",
                 type: "click",
                 handler : fn
                 }

clickEventHandlers = handleObject[];

eventsOfElem = [ clickEventHandlers, dblClickEventHandlers, .. ];

elemData = jQuery(elem);

elemData = { events :eventsOfElm, handle : bindingFn }

functionBindingFn = function (..)
{
   jQuery.event.handle.apply(eventHandle.elem, arguments );
}

elem.addEventListener( type, functionBindingFn , false );

shadow copy in jQuery

We can use jQuery to copy(clone) an object to a new object, so the old object and the new object can evolved independently.


//shadow copy object
var oldObj = { name: "fred" };
var newObj = jQuery.extend({}, oldObj);
newObj.name = "jeff";
alert(oldObj.name); //fred


To do similar thing for array, we can use [].slice() method


//clone array
var newArray = arr.slice(0);

copy array in javascript

var x = [1, 2];
var y = x.slice(0);
y[0] = 100; //y --> [100, 2]
alert(x[0]); //1
​

The new copy evolve independently of the old copy.

Mar 6, 2010

Easy Setter Functions in jquery

One of the new feature in jQuery 1.4 is setter function. For a while now, you’ve been able to pass a function into .attr() and the return value of that function is set into the appropriate attribute. This functionalilty has now been extended into all setter methods: .css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .before(), .after(), .replaceWith(), .wrap(), .wrapInner(), .offset(), .addClass(), .removeClass(), and .toggleClass(). Addtionally, for the following options, the current value of the item is passed into the function as the second argument: .css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .offset(), .addClass(), .removeClass(), and .toggleClass().

$('a[target]').attr("title", function(i, currentValue){
  return currentValue+ " (Opens in External Window)";
});

$("#xx").text(function (i, currentValue) { 
    return currentValue+ "modified by fred";
});

In jQuery 1.32, the attr is defined as follow

attr: function( name, value, type ) {
 var options = name;

 // Look for the case where we're accessing a style value
 if ( typeof name === "string" )
  if ( value === undefined )
   return this[0] && jQuery[ type || "attr" ]( this[0], name ); //jQuery.attr(this[0], name);

  else {
   options = {};
   options[ name ] = value;
  }

 // Check to see if we're setting style values
 return this.each(function(i){
  // Set all the styles
  for ( name in options )
   jQuery.attr(
    type ?
     this.style :
     this,
    name, jQuery.prop( this, options[ name ], type, i, name )
   );
 });
},

But in 1.4.2, it is defined as followed.

attr: function( name, value ) {
 //the access function is defined in core module
 return access( this, name, value, true, jQuery.attr );
},

We can see that a protected access function really does the job.

// Mutifunctional method to get and set values to a collection
// The value/s can be optionally by executed if its a function
// elems is an array
// key, value is dictionary pair
// exec is an boolean, put it true if you want to call the value as a function 
// fn is a function used to access the element
// passe is usually false, I am not sure it is intention 
function access( elems, key, value, exec, fn, pass ) {
 var length = elems.length;
 
 // Setting many attributes
 //if key is complext object like { name: "fred", age: 18 }
 if ( typeof key === "object" ) {
  for ( var k in key ) {
   access( elems, k, key[k], exec, fn, value );
  }
  return elems;
 }
 
 // Setting one attribute
 if ( value !== undefined ) {
  // Optionally, function values get executed if exec is true
  //if value is a function which dyanmically return a true value
  //and pass is null 
  //and exec is true
  //then set exec to true
  //if caller pass is undefined and caller want to evalueate the value function and value is a function
  exec = !pass && exec && jQuery.isFunction(value);
  
  //your callback function is like
  //function( elem, name, value)
  //for example
  //Query.fn.css = function( name, value ) {
  // return access( this, name, value, true, function( elem, name, value ) {
  //or function( elem, name, value, pass ) 
  //for example attr: function( elem, name, value, pass )
  for ( var i = 0; i   length; i++ ) {
   //fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
   //exec means your value to set is need to be determined by the callback functio
    var elem = elems[i];
    var valueToSet;
    if (exec)
    {
    //get the current value first
    var currentValue = fn(elem, key);
    //then call the value function to get the new value
    valueToSet = value.call(elem, i , currentValue);
    }
    else
    {
    valueToSet = value;
       }
    
    fn(elem, key, valueToSet, pass);
  }
  
  return elems;
 }
 
 // Getting an attribute
 return length ? fn( elems[0], key ) : undefined;
}

jQuery.fn.css method also used this protected method.

jQuery.fn.css = function( name, value ) {
 //rather call function(elem, name, value) call
 //access function, and let access function to call back function(elem, name, value)
 return access( this, name, value, true, function( elem, name, value ) {
  if ( value === undefined ) {
   return jQuery.curCSS( elem, name );
  }
  
  if ( typeof value === "number" && !rexclude.test(name) ) {
   value += "px";
  }

  jQuery.style( elem, name, value );
 });
};

how to test whether a object has member

Object.prototype.hasMember = function (memberName)
  {
    return memberName in this;

}
  
var attrFn = {
    val: 1,
    css: 2,
    html: 3,
    text: 4,
    data: 5,
    width: 6,
    height: 7,
    offset: 8
  };
  
alert(attrFn.hasMember("val"));

/*
don't use attrFn["val"], because is possible that you defined a member
attFn = { val : undefined }, in val is a member but its value is null,
this function also traverse the prototype chain, if you want to check direct member only use "hasOwnProperty".
*/

Mar 5, 2010

how jQuery use sizzle selector

The call stack is as follow
return new jQuery.fn.init( selector, context ); 
 return (context || rootjQuery).find( selector ); 
 jQuery.find( selector, this[i], ret ); 
return makeArray(context.querySelectorAll(query), extra ); 

//if browser does not support W3C Selectors API
//will call this
//var Sizzle = function(selector, context, results, seed) { 



//jQuery.find = Sizzle

the internal of $.end() method

jQuery methods that alter the original jQuery wrapper set selected are considered to be destructive.The reason being that they do not maintain the original state of the wrapper set. Not to worry;nothing is really destroyed or removed. Rather, the former wrapper set is attached to a new set.

pushStack: function( elems, name, selector ) {
 // Build a new jQuery matched element set
 var ret = jQuery();

 if ( jQuery.isArray( elems ) ) {
  push.apply( ret, elems );
 
 } else {
  jQuery.merge( ret, elems );
 }

 // Add the old object onto the stack (as a reference)
 ret.prevObject = this;

 ret.context = this.context;

 if ( name === "find" ) {
  ret.selector = this.selector + (this.selector ? " " : "") + selector;
 } else if ( name ) {
  ret.selector = this.selector + "." + name + "(" + selector + ")";
 }

 // Return the newly-formed element set
 return ret;
},

 end: function() {
  return this.prevObject || jQuery(null);
 },

$.extend

extend function is used to extend jQuery object. We can use it to do extend normal object, jQuery utility and jQuery method.

jQuery.extend = jQuery.fn.extend = function() { }


var x = {};
$.extend( x, {"name": "fred" });
alert(x.name); //fred
$.extend({"xxx": "fred" });
alert($.xxx); //fred

$.fn.extend( {"yyy": "jeff" });
alert($().yyy); //jeff

$(fn)

In jQuery, $(fn) is a short cut to $.fn.ready(fn). First you call the $.fn.ready(fn), in the function it call jQuery.bindReady() first, then add the fn to a readyList. In the jQuery.bindReady() function, it try to hookup DOMContentLoaded handler, in IE the event is called onreadystatechange. In the DOMContentLoaded handler, it call the jQuery.ready() function, in side of this function, the function in the readyList is invoked

if ( jQuery.isFunction( selector ) ) {
  rootjQuery.ready( selector );
}

ready: function( fn ) {
        // before hookup event, bind the real event first
 // Attach the listeners
 jQuery.bindReady();

 // If the DOM is already ready
 if ( jQuery.isReady ) {
  // Execute the function immediately
  fn.call( document, jQuery );

 // Otherwise, remember the function for later
 } else if ( readyList ) {
  // Add the function to the wait list
  readyList.push( fn );
 }

 return this;
},

bindReady: function() {
    //ensure this method is only run once
 if ( readyBound ) {
  return;
 }

 readyBound = true;

 // Catch cases where $(document).ready() is called after the
 // browser event has already occurred.
 if ( document.readyState === "complete" ) {
  return jQuery.ready();
 }

 // Mozilla, Opera and webkit nightlies currently support this event
 if ( document.addEventListener ) {
  // Use the handy event callback
  document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
  
  // A fallback to window.onload, that will always work
  window.addEventListener( "load", jQuery.ready, false );

 // If IE event model is used
 } else if ( document.attachEvent ) {
  // ensure firing before onload,
  // maybe late but safe also for iframes
  document.attachEvent("onreadystatechange", DOMContentLoaded);
  
  // A fallback to window.onload, that will always work
  window.attachEvent( "onload", jQuery.ready );

  // If IE and not a frame
  // continually check to see if the document is ready
  var toplevel = false;

  try {
   toplevel = window.frameElement == null;
  } catch(e) {}

  if ( document.documentElement.doScroll && toplevel ) {
   doScrollCheck();
  }
 }
},

if ( document.addEventListener ) {
 DOMContentLoaded = function() {
  document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
  jQuery.ready();
 };

} else if ( document.attachEvent ) {
 DOMContentLoaded = function() {
  // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
  if ( document.readyState === "complete" ) {
   document.detachEvent( "onreadystatechange", DOMContentLoaded );
   jQuery.ready();
  }
 };
}

jQuery is an array like object

In javascript, array is object, so there are lots benefit to use array object, like the length, index, slice. jQuery is a collection of element, so use it as an array is very convenient. it seems to me that jQuery object can not use array as prototype for some reason, so how we can use an object like an array, please read the following code.

var x = {};
x[0] = "zero";
x[1] = "one"

var array =  Array.prototype.slice.call(x, 0 );
alert(array .length); //0
  
alert(x[0]);
alert(x.length); //undefined
alert(x instanceof Array); //x is not an array

Array.prototype.push.call(x, "zero overwritten");
alert(x[0]); //zero x
alert(x[1]); //one
alert(x.length); //now looks like an array, but the it is till 1

array =  Array.prototype.slice.call(x, 0 );
alert(array .length); //1


Array.prototype.push.call(x, "one overwritten");
alert(x[1]); //one x
alert(x.length); //2, length is determine how many elements your push

array =  Array.prototype.slice.call(x, 0 );
alert(array .length); //2

Mar 4, 2010

arguments.callee

var sum = function(i)
{
  if (i == 1)
  {
    return i; 
  }
  else 
  {
    
   return i + arguments.callee(i-1); 
  }
}
alert(sum(3));
​

makeArray function

function highest(){ 
  //return arguments.slice(1).sort(function(a,b){ 
  return makeArray(arguments).sort(function(a,b){ 
    return b - a; 
  }); 
} 
 
function makeArray(array){ 
  return [].slice.call( array ); 
} 

Mar 2, 2010

change in mvc2 project

  1. project file change, replace guid {603c0e0b-db56-11dc-be95-000d561079b0} with {F85E285D-A4E0-4152-9332-AB1D724D3325} in ProejctTypeGuids nodes
  2. Reference dll change, update all reference in web.config files and project files update runtime binding.
    <runtime>  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">    <dependentAssembly>      
    <assemblyIdentity name="System.Web.Mvc"           publicKeyToken="31bf3856ad364e35"/>      <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>    </dependentAssembly>  </assemblyBinding></runtime>
    
  3. javascript file changes, copy new script from new project to old project