friday links 6

  1. SerialSeb: Why Mock frameworks suck, and how to write delegate-based test doubles
  2. Mocks and Stubs – The difference is in the flow of information – Blog – Osherove
  3. Mocks Aren't Stubs
  4. Configuring Relationships with Fluent API
  5. Some myths of 'Textbook-TDD', and why they are wrong
  6. Mocking Comparison – Part 1: The Basics : Richard Banks – Agile and .NET
  7. A delicious toolbox
  8. The Pragmatic Bookshelf | PragPub 2011-11 | Self-Inflicted Scope Creep
  9. Scott Hanselman's 2009 Ultimate Developer and Power Users Tool List for Windows – Scott Hanselman
  10. Seeing the SQL Generated by LINQ to Entity Queries — Visual Studio Magazine
  11. I am a programmer | jacquesmattheij.com
  12. Don’t Call Yourself A Programmer, And Other Career Advice | Kalzumeus Software
  13. Monitoring SQL Server database transaction log space
  14. MSSQLTips Contribute
  15. 9GAG – Seems legit
  16. 20 Innovative Startups
  17. Setup – App Inventor for Android
  18. 25 Secrets of the Browser Developer Tools – AndiSmith.com
  19. Field Level Auditing using Change Data Capture – Part 2 – SQLServerCentral
  20. Update 4.0.2 for Microsoft .NET Framework 4 – Runtime Update
  21. Building HTML5 Applications – Better Web Forms with HTML5 Forms
  22. Universal Type Extender – CodeProject
  23. My 3 Favorite Connection String Tips | Brent Ozar PLF | Brent Ozar PLF
  24. mvc-mini-profiler – A simple but effective mini-profiler for ASP.NET and WCF – Google Project Hosting
  25. Home // Think Like (a) Git
  26. On Programming Deadlines – Randall Degges
  27. A List Apart: Articles: Dark Patterns: Deception vs. Honesty in UI Design
  28. Roach Motel – Dark Patterns
  29. Store / Xamarin
  30. Extending DataTables Range Filter – CodeProject
  31. Rapid Prototyping For Any Device With Foundation – Smashing Coding
  32. ASP.NET MVC: Expression Trees as Parameter to Simplify Query – CodeProject
  33. HTML Parsing with JavaScript – davidflanagan.com
  34. JavaScript in the small | Ola Bini: Programming Language Synchronicity
  35. Extension Method to help with EF Code First updating – CodeProject
  36. nVLC – CodeProject
  37. Fast Track to the Mobile App – Windows Phone App Design Challenge by Core77
  38. WCF Data Services Providers – CodeGuru
  39. How To Successfully Compete With Open Source Software
  40. Why I’m Done Making Desktop Applications: MicroISV on a Shoestring
  41. Work Less, Get More Done: Analytics For Maximizing Productivity | Kalzumeus Software
  42. Developers and Professionalism – Girl Developer
  43. Globalization, Internationalization and Localization in ASP.NET MVC 3, JavaScript and jQuery – Part 1 – Scott Hanselman
  44. NuGet gallery
  45. galaktor's blawg

Differences MVC versus WebForms

Rule of thumb for differences between ASP.NET MVC versus ASP.NET WebForms 1 :

  1. If it is a Web Form Control ( asp:textbox, asp:gridview) it does not work in MVC. Period. 2. Use DisplayTemplates/EditorTemplates/PartialView/HtmlHelpers and some jquery (or your favorite javascript framework) magic. See http://msprogrammer.serviciipeweb.ro/2010/05/30/mvc-helper-templates .3
  2. Security is NOT on web.config ( location ). Security is on Actions. ( Authorize or derive from ). However, enforce your Repository /Business Layer for security. Do not rely unique on Web security.
  3. Anything else it works in MVC like in WebForms . ( it means Session, Cache, Application, Cookies , IIS and so on)1. However, please note that MVC have TempData, ViewData, Filters, Models4 , ModelBinders4 and more features . Please learn those as they are important to MVC.

Notes:
1 : I am not using anymore WebForms. Too troublesome getting all those events. And which order it is when Ajax comes in action?! And I can tell you another 1000 reasons. But please follow tutorials from http://www.asp.net/mvc

2 : Ok, ok, it might work on display on HttpGet. But on HttpPost in 99,99% cases no.And no events. And will be more troublesome than advantages! So basic instinct: NO WEB FORMS CONTROLS ON ASP.NET MVC!

3No, the login controls are not available in MVC. Did you take a chance to see the default source code for a new MVC template ? There are controller and partial views implemented. Even remote validations! (Please follow tutorials from http://www.asp.net/mvc)

4 Ok, ok,so ASP.NET vNext will have strongly typed Models on controls.  And a ModelBinding over ValueProviders ( see [QueryString] on this post ) . But see note 1

friday links 5

  1. New cool list of Linux must-have programs
  2. calvin.jpg (JPEG Image, 900×628 pixels)
  3. Google App Inventor – CodeProject
  4. My 3 Favorite Connection String Tips | Brent Ozar PLF | Brent Ozar PLF
  5. Fast Track to the Mobile App – Windows Phone App Design Challenge by Core77
  6. Author information in search results – Webmaster Tools Help
  7. NuGet – Manage Project Libraries with NuGet
  8. Ubuntu One : Downloads : Windows : More Info
  9. mvc-mini-profiler – A simple but effective mini-profiler for ASP.NET and WCF – Google Project Hosting
  10. Home // Think Like (a) Git
  11. On Programming Deadlines – Randall Degges
  12. A List Apart: Articles: Dark Patterns: Deception vs. Honesty in UI Design
  13. I am a programmer | jacquesmattheij.com
  14. Roach Motel – Dark Patterns
  15. Store / Xamarin
  16. Extending DataTables Range Filter – CodeProject
  17. Rapid Prototyping For Any Device With Foundation – Smashing Coding
  18. ASP.NET MVC: Expression Trees as Parameter to Simplify Query – CodeProject
  19. 4.3 Scripting — HTML Standard
  20. HTML Parsing with JavaScript – davidflanagan.com
  21. JavaScript in the small | Ola Bini: Programming Language Synchronicity
  22. Extension Method to help with EF Code First updating – CodeProject
  23. nVLC – CodeProject
  24. Getting Started: Syntax Analysis
  25. WCF Data Services Providers – CodeGuru
  26. How To Successfully Compete With Open Source Software
  27. Why I’m Done Making Desktop Applications: MicroISV on a Shoestring
  28. Work Less, Get More Done: Analytics For Maximizing Productivity | Kalzumeus Software
  29. Don’t Call Yourself A Programmer, And Other Career Advice | Kalzumeus Software
  30. Developers and Professionalism – Girl Developer
  31. Building HTML5 Applications – Better Web Forms with HTML5 Forms
  32. shanselman / Psuedoizer / overview — Bitbucket
  33. Globalization, Internationalization and Localization in ASP.NET MVC 3, JavaScript and jQuery – Part 1 – Scott Hanselman
  34. NuGet gallery
  35. galaktor’s blawg
  36. Setup – App Inventor for Android

Programmer tools 2011

List of programmer tools

I have re-installed the PC and I have been taken notice of what tools I have on the system now:

  1. Magic Disc – can mount .iso files ( for  2 )
  2. Visual Studio – must have for a easy developing path
  3. Sql Server 2008 – primary database for me
  4. 7-zip  – archiver
  5. Firefox ( plus addons, see below)
  6. Smtp4dev – to see messages
  7. AspNetMVC3ToolsUpdateSetup
  8. FreeCommander –  dual panels for windows explorer
  9. Foxit reader – pdf viewer
  10. Notepad ++ ( with hex addon)
  11. Winmerge – files/ folders difference
  12. Clean project – archive solution
  13. SqlSearch from RedGate – fast search after names
  14. SSMS tools – record every operation you do in sql server
  15. EntityFramework41  – code first development
  16. XUnit – automated testing + samples  to do BDD style
  17. SSCERuntime_x86-ENU –SqlCompact provider. Works with EF4.1
  18. SqlCe40Toolbox – SqlCompact viewer
  19. NuGet.Tools.vsix – Nuget is awesome!
  20. ImgBurn  – burn cd-s
  21. consolas font  – see  1 and l ?
  22. LogParser  – never know when you need to parse some files
  23. Moq  – mocking tool
  24. PreviewHandlerPack  -see c# code in preview window
  25. Regulator and Regulazy – regular expression helpers
  26. StringTemplate.NET  – templating generator. Maybe replaced by razor ?
  27. NLog –  logging tool. Log4Net was pretty unreliable in .NET 4
  28. FileHelpers – reading writing text data.
  29. Tcmdwincearm – Total Commander for mobile. Free.
  30. Jquery and Jquery UI.
  31. DataTables – html tables supports sorting , filtering, others.
  32. Windows Live Essential – blogging fast.
  33. InsertFilePlugin – Live writer extension to insert files to upload.
  34. OfficeOpenXMLPart4-MarkupLanguageReference  – markup for Office XML. Used with StringTemplate
  35. SharpZipLib – knows how to zip multiple files.
  36. AutoFixture – generating sample data
  37. HtmlAgilityPack – parsing web pages
  38. T4MVC – get rid of magic names for controllers, actions
  39. Itextsharp – save as pdf
  40. Ninject – DI provider
  41. Hudson – continous integration
  42. AutoMapper  – transferring data between DAL and BLL
  43. Selenium – testing web interfaces
  44. Svn  -source control
  45. MVC Contrib – pages list and more
  46. Msbuildtask from tigris – build make it easy
  47. Psr – help made easy in Windows 7
  48. Firefox addons here

https://addons.mozilla.org/en-US/firefox/collections/ignatandrei/ignatandrei/

For every tool search for it . The first link will give you all details.

You can have as pdf here:List of programmer tools 2011

Implementations GUI details

When creating a GUI you must think to give user some good feeling about what the software can do – so I started to MVC 4 website, that have mobile support integrated.

More, you must demonstrate some features right away to the user – so what’s best if not a message from system admin to the user  to “welcome” him ?

For this , I have to  implement a template with RazorEngine – simple to used from his code

string template = "Hello @Model.Name! Welcome to Razor!";
  string result = Razor.Parse(template, new { Name = "World" });

Summary of modifications for this simple operation – send and display a message  from Admin when a user registers

  1. Add connectionstrings to web.config – to connect to database + SiteUtils static class to retrieve it.
  2. RegisterAdmin user in Application_Start – in order to have user Admin in the database ( generate a GUID and put into a const)
  3. Add “welcome.txt” file
  4. Add RazorEngine to parse message
  5. Modify  Register action in order to send message after a user registers
  6. Add an area “Messaging” in order to can have the messaging separated from main site( to be easier to xcopy)
  7. Add an Index action( display read/unread messages) + View
  8. Add an DisplayMessage action (display a message) + View

All for this picture where it shows number of unread messages(1) and list :

image

You will find code at http://messagemvc.codeplex.com/SourceControl/changeset/changes/81924

Homework:

Think about the user actions . He will be interested in the following for existing messages:

  1. Unread messages
  2. View of all messages (paginating)
  3. Search messages:
    • Messages from a date
    • Messages from someone
    • Search

What do you think it will be done for implementing those?

Creating Edmx files and testing

The favorite ORM in .NET world for me it is edmx files. It gives you the database plain – and have generators for POCO (http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx) as for EF4.1 DBContext(http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-model-amp-database-first-walkthrough.aspx).

I will use this one – because of the new ! But the template is over simplistic  -so I improved . I do not want you to bother you with my experience – I want to say that, after playing with Data attributes – I decide that Fluent Configuration suits all. The template is here:

DBContext-SecondVersion.zip

 

For example, the default template

Also for testing I use the fact the default EF4.1  Model1.Context.tt generates this code:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

( see playing on safe side to NOT drop the existing database?!)

Mine Model1.Context.tt generates this:


 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
    		var prefix = System.Configuration.ConfigurationManager.AppSettings["prefixTable"]??"";
    		bool Continue=true;
            OnBeginModelCreating(modelBuilder,prefix, ref Continue);
    		if(!Continue)
    			return;
    
    		//construct default
    		#region smsg_Message 
    		modelBuilder.Entity<smsg_Message>().ToTable(prefix  + "smsg_Message");
    		modelBuilder.Entity<smsg_Message>().HasKey(item => item.IDMessage);
    
    
    		#endregion
    		#region smsg_Message_Archive 
    		modelBuilder.Entity<smsg_Message_Archive>().ToTable(prefix  + "smsg_Message_Archive");
    		modelBuilder.Entity<smsg_Message_Archive>().HasKey(item => item.IDMessageArchive);
    
    
    		#endregion
    		#region smsg_MessageThread 
    		modelBuilder.Entity<smsg_MessageThread>().ToTable(prefix  + "smsg_MessageThread");
    		modelBuilder.Entity<smsg_MessageThread>().HasKey(item => item.IDMessageThread);
    
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessage_IDMessageInitial)
                    .WithMany(u => u.IDMessage_IDMessageInitial)
                    .HasForeignKey(x => x.IDMessageInitial)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessage_IDMessageReply)
                    .WithMany(u => u.IDMessage_IDMessageReply)
                    .HasForeignKey(x => x.IDMessageReply)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessageArchive_IDMessageInitial)
                    .WithMany(u => u.IDMessageArchive_IDMessageInitial)
                    .HasForeignKey(x => x.IDMessageInitial)
                    .WillCascadeOnDelete(false);
    
    		
    		modelBuilder.Entity<smsg_MessageThread>()
                    .HasRequired(item => item.IDMessageArchive_IDMessageReply)
                    .WithMany(u => u.IDMessageArchive_IDMessageReply)
                    .HasForeignKey(x => x.IDMessageReply)
                    .WillCascadeOnDelete(false);
    
    		
    
    		#endregion
    	
    		OnFinishModelCreating(modelBuilder, prefix);
    		
        }

More, for giving you a smell of what the templates generates, look at this function for reading messages sent:


 public  IEnumerable<IUserMessage<IUser<String>,string>> RetrieveMessageSent(DateTime dt)
        {
            using (smsg_Message_List ml = new smsg_Message_List(ConnectionMessaging))
            {
                ml.LoadFromDB.AddToCustomPredicate(smsg_Message_FindDB.fexp_FromUser(this.Key));
                ml.LoadFromDB.AddToCustomPredicate(smsg_Message_FindDB.fexp_DateInsertedBetweenEqDate(dt, dt));
                ml.LoadFromDB.LoadFindCustomPredicate();
                return ml;
            }
        }

The class smsg_Message_List and the AddToCustomPredicate , LoadFindCustomPredicate and the expression fexp_FromUser and fexp_DateInsertedBetweenEqDate are automatically generated by the template.
I do not think that the template is perfect – it just helps me a lot!

For the database tests, I was thinking of NUnit – but was deprecated by xUnit. It has a nice project, named SpecificationExample – and it generates data in BDD style .
For example, this code:


 public void CreateUsersAndSendMessage()
        {
            
            List<SimpleUser> users = null;

            "When create two users".Context(() => users = CreateUsersAndDeleteItFirst());
            "it will be friends".Assert(() => FindFriend(users).ShouldNotBeNull());
            
            "and when send message from first user to second user".Do(() => SendMessage(users));

            
            "we will retrieve it searching message from first user ".Assert(() => RetrieveMessageSent( users[0]).ShouldEqual(1));

            "we will NOT retrieve it searching message from second user".Assert(() => RetrieveMessageSent(users[1]).ShouldEqual(0));

            "we will retrieve searching messages received by second user".Assert(() => RetrieveMessageReceived(users[1]).ShouldEqual(1));

            "we will retrieve count of unread messages :1 ".Assert(() => RetrieveMessageUnreadCount(users[1]).ShouldEqual(1));

            


        }

run by this command:

xunit.console.clr4.x86.exe "$(TargetPath)" /html "$(TargetDir)a.html" 

in Build events it will generate the following HTML


————————————————————————

✔  When create two users and when send message from first user to second user, it will be friends

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.060s

✔  When create two users and when send message from first user to second user, we will NOT retrieve it searching message from second user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.099s

✔  When create two users and when send message from first user to second user, we will retrieve count of unread messages :1

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.032s

✔  When create two users and when send message from first user to second user, we will retrieve it searching message from first user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

0.053s

✔  When create two users and when send message from first user to second user, we will retrieve searching messages received by second user

Output
Before : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage
After : testXunit.clsTestUserSendMessage.CreateUsersAndSendMessage

—————————————–


Nice , isn’t it?

Homework :
1. use the ITLIst.tt template , search for

//TODO: prefix

and make generating same prefix for the table as in the Model1.Context.tt( search prefix)
( Do not forget the change the edmx file name in the .tt file!)
2. Make a .t4 file to share commonalities( such as edmx name)

Interfaces and more

 

Summary:

If you want common behavior, you need an interface. And from the first one is a small step to re-organizing the program.

Body:

When you make a component for other people, you must make the possibility for those to

1. customize your software with their software

2. provide a default implementation

For the messaging component, the first customization is to provide a way for the site using the messaging to use their users.

The first step is to create a custom project which can provide guidance to the users that want to implement. VS provides XML documentation –I have checked and put also “warnings as error”

clip_image002

Next , I have create the User interface:

/// <summary>
    /// the user that can send messages
    /// TODO version 2: make pagination
    /// </summary>
    /// <typeparam name="UserPrimaryKey">the type of primary key</typeparam>
    public interface IUser<UserPrimaryKey>
    {
        /// <summary>
        /// the user primary key
        /// </summary>
        UserPrimaryKey Key { get; set; }
        /// <summary>
        /// the user name to be displayed
        /// </summary>
        string UserNameToDisplay { get; set; }
        /// <summary>
        /// other info for the user
        /// </summary>
        string OtherInfo { get; set; }

        /// <summary>
        /// find friends
        /// </summary>
        /// <param name="search">find user by name</param>
        /// <returns></returns>
        IEnumerable<KVPNew<UserPrimaryKey, string>> FindFriends(string search);

        /// <summary>
        /// find friends online
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        IEnumerable<KVPNew<UserPrimaryKey, string>> FindFriendsOnline(string search);

        /// <summary>
        /// sends a message 
        /// </summary>
        /// <param name="message"></param>
        void SendMessage(IUserMessage<IUser<UserPrimaryKey>, UserPrimaryKey> message);

    }
 

Two methods are interesting : SendMessage and FindFriends

Let’s take first SendMessage. It was obviously clear that I need another interface – the message to be sent. So the next interface created:

/// <summary>
    /// the message to be sent to the user
    /// TODO version 2: allow messaging for more than 1 user
    /// TODO version 2: message importance
    /// </summary>
    /// <typeparam name="TheUser">user interface</typeparam>
    ///  /// <typeparam name="UserPrimaryKey">user primary key</typeparam>
    public interface IUserMessage<TheUser, UserPrimaryKey>
        where TheUser : IUser<UserPrimaryKey>
    {
        /// <summary>
        /// subject of the message
        /// </summary>
        string Subject { get; set; }
        /// <summary>
        /// body of the message
        /// </summary>
        string Body { get; set; }
        /// <summary>
        /// to the user
        /// </summary>
        TheUser To { get; set; }
        /// <summary>
        /// from the user
        /// </summary>
        TheUser From { get; set; }
        /// <summary>
        /// cc - as in email
        /// </summary>
        TheUser CC { get; set; }

        /// <summary>
        /// date of message
        /// </summary>
        DateTime DateInserted { get; set; }

        /// <summary>
        /// if recipient have read
        /// </summary>
        bool MessageRead { get; set; }
        // <summary>
        // bcc - as in email
        // </summary>
        //TheUser BCC { get; set; }



    }

Let’s take the other : IEnumerable<KVPNew<UserPrimaryKey, string>> FindFriends(string search);

It is clear that a user can send emails to friends( maybe to anybody if we make an intranet site for an enterprise) and I must somehow have the names and id’s of the friends. I could use KeyValuePair – but it is a struct and can not be compared with null . More, usually I need more data to be transferred – so I have created long ago a KVPNew class:

 /// <summary>
    /// this is the correspondent class of KeyValuePair structure from .net
    /// The features:
    /// 1. it is a class-  can be compared fastly with null
    /// 2. can be used in a search and display <paramref name="AdditionalData">AdditionalData </paramref>
    /// </summary>
    /// <typeparam name="TKEY">Key - it is compared in equals and GetHashCode</typeparam>
    /// <typeparam name="TValue">Value to be displayed</typeparam>
    public class KVPNew<TKEY, TValue>
    {
        public KVPNew() { }
        public KVPNew(TKEY key, TValue value):this()
        {
            this.Key = key;
            this.Value = value;

        }
        public TKEY Key { get; set; }
        public TValue Value { get; set; }
        public string AdditionalData { get; set; }
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;

            var o = obj as KVPNew<TKEY, TValue>;
            if (o == null)
                return false;
            return this.Key.Equals(o.Key);

        }
        public override int GetHashCode()
        {
            return this.Key.GetHashCode();
        }
    }

And, being to interfaces, I have created also an interface for admin people to find users

/// <summary>

/// used by application to load plugins to find users

/// because each application can have it’s own way to find users

/// <summary>
    /// used by application to load plugins to find users
    /// because each application can have it's own way to find users
    /// used by admins to find users
    /// Improvement version 2 : pagination 
    /// </summary>
    /// <typeparam name="T">user </typeparam>
    /// <typeparam name="UserKey">user key </typeparam>
    public interface IUsersFind<T,UserKey>
        where T:IUser<UserKey>
    {
        /// <summary>
        /// used to find users online to send message
        /// </summary>
        /// <param name="UserThatMakesTheSearch"> the user that makes the search </param>
        /// <param name="Search">search string - could be null</param>
        /// <returns> a list of users</returns>
        IEnumerable<KVPNew<T, string>> FindUsersOnline(T UserThatMakesTheSearch, string Search);
        /// <summary>
        /// used to find users (online or not )to send message
        /// </summary>
        /// <param name="UserThatMakesTheSearch"> the user that makes the search </param>
        /// <param name="Search">search string - could be null</param>
        /// <returns> a list of users</returns>
        IEnumerable<KVPNew<T, string>> FindUsers(T UserThatMakesTheSearch, string Search);
        /// <summary>
        /// find a user by his key
        /// </summary>
        /// <param name="key">the user key</param>
        /// <returns></returns>
        IUser<UserKey> FindUser(UserKey key);
            
    }


/// <summary>
    /// operations with the database
    /// </summary>
    /// <typeparam name="User"></typeparam>
    /// <typeparam name="UserPrimaryKey"></typeparam>
    public interface IUserList<User, UserPrimaryKey>: IDisposable
        where User : IUser<UserPrimaryKey>
    {
        /// <summary>
        /// fast delete all from database - good for testing
        /// </summary>
        void FastDeleteAll();
        
        /// <summary>
        /// add to internal list
        /// </summary>
        /// <param name="u">the user to be added </param>
        void Add(User u);
         
        /// <summary>
        /// save changes for new and old members
        /// </summary>
        void SaveNew();
        /// <summary>
        /// save changes for old members
        /// </summary>
        void SaveExisting();

        /// <summary>
        /// for retrieving 
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        User Find(int i);
        
    }

The final interfaces are in this picture:

clip_image004

Next time we will create the database EF4.1 files from DatabaseFirst and we will modify .tt templates to behave nicely with relationships.

Homework:

  • Add to IUserMessage a BCC field
  • What if To from IUserMessage will be directed to more than one person ?How do you implement it?
  • Do you think that is something missed from KVPNew class?( Hint == operator and GetHashCode)

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.