MSDN Channel 9 has posted a First Look video.
Phones are from Dell, LG, HTC and Samsung.
A .NET and Visual Studio blog.
MSDN Channel 9 has posted a First Look video.
Phones are from Dell, LG, HTC and Samsung.
This is the second post in this series.
The first thing we need to do to enable using our POCOs with EF 4.0 is to decide how we want to handle change tracking and lazy loading of our child collections.
For now, let’s take full advantage of EF’s capabilities and allow it to generate the proxies for lazy loading and full change tracking.
To do this, there are four requirements:
Since List<T> is an implementation of ICollection<T>, we can keep it for our collection, but we need to mark all the properties as virtual. Here are our entities:
using System.Collections.Generic;
namespace Entities.School
{
public class Department
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual List<Course> Courses { get; set; }
}
public class Course
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual Department Department { set; get; }
}
}
Note that I have removed the code that kept the Department.Courses collection in sync, when the Course.Department is set. I had hoped that the proxy behavior would replace this “default” behavior, but it looks like from my testing that the proxy synchronization takes place, followed by the “base” behavior. This resulted in two entries being made in the Courses collection each time a Course was assigned to the Department. I removed the base behavior, which means that if the in-memory repository is used, the client code will need to synchronize the collection.
Next, we create the model. Right-click on the model canvas and select Generate Database from Model. This will create the DDL script to create the tables.
Next, blank out the Custom Tool property on the file properties for the EDMX file. This way, no code will be generated for your model. This means we need to write our own ObjectContext class. Many authors recommend creating strongly-type properties for exposing each ObjectSet (Departments, Courses). You can do that, but it isn’t very useful for our Repository interface. Rather, we will create Query<T> and SetOf<T> methods to return the appropriately typed IQueryable and ObjectSet, respectively.
using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
namespace Model
{
public class PocoContext : ObjectContext
{
public PocoContext(string connectString)
: base(connectString)
{
ContextOptions.LazyLoadingEnabled = true;
}
Dictionary<Type, ObjectQuery> roots = new Dictionary<Type, ObjectQuery>();
public ObjectSet<T> SetOf<T>() where T : class
{
ObjectQuery root;
if (!roots.TryGetValue(typeof(T), out root))
{
var set = CreateObjectSet<T>();
roots[typeof(T)] = set;
return set;
}
return (ObjectSet<T>)root;
}
public IQueryable<T> Query<T>() where T : class
{
return (IQueryable<T>)SetOf<T>();
}
}
}
Finally, we create our Repository implementation.
using System.Linq;
namespace Model.School.Model2
{
using Interfaces;
public class SchoolRespository : BaseRepository
{
private PocoContext context;
public SchoolRespository(string connectString = "name=Model2Container")
{
context = new PocoContext(connectString);
}
public override IQueryable<T> Query<T>()
{
return context.Query<T>();
}
public override T New<T>()
{
return context.CreateObject<T>();
}
public override void SetNext<T>(T obj)
{
// no need for this with SQL Server auto-numbering
}
public override void Add<T>(T obj)
{
context.SetOf<T>().AddObject(obj);
}
public override void Remove<T>(T obj)
{
context.SetOf<T>().DeleteObject(obj);
}
public override void Commit()
{
context.SaveChanges();
}
}
}
Here is a test that shows how to use the SchoolRepository that we have created.
[TestMethod]
public void Test_SchoolRepository()
{
IRepository repo = new SchoolRespository();
var count = repo.Query<Department>().Count();
try
{
var math = repo.CreateNext<Department>(d =>
{
d.Name = "Mathematics";
});
var algebra = repo.CreateNext<Course>(c =>
{
c.Name = "Algebra";
c.Department = math;
});
repo.Commit();
repo = new SchoolRespository();
var course = (from c in repo.Query<Course>()
where c.Name == "Algebra"
select c).First();
Assert.IsNotNull(course);
Assert.IsTrue(course.Department.Id == math.Id);
var dept = (from d in repo.Query<Department>()
where d.Name == "Mathematics"
select d).First();
Assert.IsTrue(dept.Courses.Count == 1);
Assert.IsTrue(dept.Courses[0] == course);
}
finally
{
repo = new SchoolRespository();
// remove course and dept
var course = repo.Query<Course>()
.Where(o => o.Name == "Algebra").FirstOrDefault();
if (course != null) repo.Remove<Course>(course);
var dept = repo.Query<Department>()
.Where(o => o.Name == "Mathematics").FirstOrDefault();
if (dept != null) repo.Remove<Department>(dept);
repo.Commit();
}
}
While I know there are a lot of people in the ALT.NET community who like to mock Enitity Framework, that is not what I am talking about.
The objective of this exercise is to develop an Interface that can be used by Business Logic to query and persist data as well as provide and in-memory “mock” for testing or prototyping without a database.
The paradigm used is that of object model aggregates typically found in Domain-driven designs (DDD). This is fortunate because it is the model used by EF, where the aggregates are called ObjectSets.
We want to take advantage of LINQ, because this will allow the consumer of the Repository to add query operators prior to executing the query. The Repository will provide a Query method, a New method, an Add method, a Remove method and a Commit method.
I used the term “a repository-like facade” in the title of this post because traditionally a Repository provides access to a single Aggregate. I have decided to allow an EF Context, which might have several aggregates, to be wrapped by my Repository-implementation. The root aggregate type is determined by the Type parameter affixed to the method. In addition, I will provide a number of convenience methods to chain some of these basic methods is a single method call.
Here is the interface:
using System;
using System.Linq;
namespace Interfaces
{
public interface IRepository
{
// returns a query object for an aggregate root
IQueryable<T> Query<T>();
// returns a new object of the type requested
T New<T>() where T : class;
// returns a new object of the type requested (with the next id set)
T Next<T>() where T : class;
// adds the object to the aggregate root
void Add<T>(T obj) where T : class;
// gets a new object and Adds it to the collection
T AddNew<T>() where T : class;
// gets a new object (with next id set) and Adds it to the collection
T AddNext<T>() where T : class;
// adds a new object with the next id, runs initializer and persists it
T CreateNext<T>(Action<T> initializer) where T : class;
// remove an aggregate root
void Remove<T>(T obj) where T : class;
// persists any changes
void Commit();
}
}
The following code is an abstract implementation of the convenience methods, which are independent of the actual method of creating the new objects and managing them in the context. The methods that are declared abstract are the ones that will need to be implemented by a concrete Repository.
Note: The exception handling in these code listings has been omitted for brevity.
using System;
using System.Linq;
namespace Interfaces
{
abstract public class BaseRepository : IRepository
{
abstract public IQueryable<T> Query<T>();
abstract public T New<T>() where T : class;
abstract public void SetNext<T>(T obj) where T : class;
abstract public void Add<T>(T obj) where T : class;
abstract public void Remove<T>(T obj) where T : class;
abstract public void Commit();
public T Next<T>() where T : class
{
var obj = New<T>();
SetNext<T>(obj);
return obj;
}
public T AddNew<T>() where T : class
{
var obj = New<T>();
Add<T>(obj);
return obj;
}
public T AddNext<T>() where T : class
{
var obj = Next<T>();
Add<T>(obj);
return obj;
}
public T CreateNext<T>(Action<T> initializer) where T : class
{
var obj = AddNext<T>();
if (initializer != null) initializer(obj);
Commit();
return obj;
}
}
}
We can implement an in-memory repository that maintains each type of aggregate root in an ArrayList and uses the Type to find the correct List and operate on it accordingly. To simulate auto-numbered primary keys, we assume that auto-numbered entities will have a long Id property and maintain a single counter for all entities. Of course, you are free to implement this any way that works for you. The Commit() method is a no-op since we don’t plan on persisting the data to disk, but you can implement a Repository that does this if you like.
This implementation works with concrete entity classes (POCOs). I originally had a version that worked with interfaces and the repository mapped the interfaces to an implementation. This worked well with Entity Framework and its generated EntityObject classes, but fell down when I tried to use it with WCF RIA Services.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Interfaces
{
public class InMemRepository : BaseRepository
{
public InMemRepository()
{
// could data load from disk here
}
Dictionary<Type, ArrayList> roots = new Dictionary<Type, ArrayList>();
long counter = DateTime.Now.Ticks;
private ArrayList GetRootList<T>()
{
ArrayList list;
if (!roots.TryGetValue(typeof(T), out list))
{
list = new ArrayList();
roots[typeof(T)] = list;
}
return list;
}
public override IQueryable<T> Query<T>()
{
var list = GetRootList<T>();
return list.Cast<T>().AsQueryable<T>();
}
public override T New<T>()
{
return Activator.CreateInstance<T>();
}
// assumes that there is an Id property (long)
public override void SetNext<T>(T obj)
{
var idProperty = typeof(T).GetProperty("Id");
idProperty.SetValue(obj, counter++, null);
}
public override void Add<T>(T obj)
{
var list = GetRootList<T>();
list.Add(obj);
}
public override void Remove<T>(T obj)
{
var list = GetRootList<T>();
list.Remove(obj);
}
public override void Commit()
{
// code here to write to disk
}
}
}
Here is a unit test that demonstrates how to work with the repository:
[TestClass()]
public class InMemRepositoryTest
{
public class Department
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
private IList<Course> _courses = new List<Course>();
public virtual IList<Course> Courses { get { return _courses; } }
}
public class Course
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
private Department _department;
public virtual Department Department { get { return _department; }
set
{
if (_department != null) _department.Courses.Remove(this);
_department = value;
if (_department != null) _department.Courses.Add(this);
}
}
}
[TestMethod]
public void Test_InMemRepository()
{
IRepository repo = new InMemRepository();
// create some departments
var math = repo.AddNext<Department>();
Assert.IsNotNull(math);
Assert.IsInstanceOfType(math, typeof(Department));
Assert.IsTrue(math.Id > 0);
math.Name = "Mathematics";
repo.Commit();
// use the convenience method
var compsci = repo.CreateNext<Department>(d =>
{
d.Name = "Computer Science";
});
Assert.IsNotNull(compsci);
Assert.IsInstanceOfType(compsci, typeof(Department));
Assert.IsTrue(compsci.Id > 0);
Assert.IsTrue(compsci.Name == "Computer Science");
var count = repo.Query<Department>().Count();
Assert.AreEqual<int>(count, 2);
// create some courses
var algebra = repo.CreateNext<Course>(c =>
{
c.Name = "Algebra";
c.Department = math;
});
var trig = repo.CreateNext<Course>(c =>
{
c.Name = "Trigonometry";
c.Department = math;
});
var lisp = repo.CreateNext<Course>(c =>
{
c.Name = "Lisp";
c.Department = math;
});
Assert.AreEqual<int>(3, repo.Query<Course>().Count());
Assert.AreEqual<int>(3, math.Courses.Count());
Assert.AreEqual<int>(0, compsci.Courses.Count());
lisp.Department = compsci;
Assert.AreEqual<int>(2, math.Courses.Count());
Assert.AreEqual<int>(1, compsci.Courses.Count());
}
}
My next post will show how to write a Repository implementation for Entity Framework.
Due to rumors swiling about the demise of Silverlight at the hands of HTML 5, Microsoft felt compelled to publish the following on the Silverlight Blog:
In about half the time HTML 5 has been under design, we've created Silverlight and shipped four major versions of it. And it's still unclear exactly when HTML 5 and its related specs will be complete with full test suites. For HTML 5 to be really targetable, the spec has to stabilize, browsers have to all implement the specs in the same way, and over a billion people have to install a new browser or buy a new device or machine. That's going to take a while. And by the time HTML 5 is broadly targetable, Silverlight will have evolved significantly. Meanwhile, Silverlight is here now and works in all popular browsers and OS's.
…Silverlight is much more than a browser technology.
There are three areas of investment for Silverlight outside the browser: the desktop, the mobile device, and the living room. Powerful desktop applications can be created with Silverlight today. These applications don't require a separate download—any desktop user with Silverlight installed has these capabilities. These apps can be discovered and downloaded in the browser but are standalone applications that are painless to install and delete. Silverlight now also runs on mobile devices and is the main development platform for the new Windows Phone 7 devices. Developers that learned Silverlight instantly became mobile developers. Lastly, at NAB and the Silverlight 4 launch this year we showed how Silverlight can be used as a powerful, rich platform for living room devices as well.
Read the whole thing. It’s long but worth the time.
Microsoft has released a refresh for Silverlight 4 to fix some bugs. Read Tim Heuer’s blog post.
If you are developing in LightSwitch, then you will need the new Developer Runtime and SDK.
The Silverlight Tools package has also been updated with the new SDK and runtime.
According to a tweet from Scott Guthrie, Windows Phone 7 is released to manufacturing today. The final tools will be ready for download in two weeks, on September 16.
VS 2010 Express for Windows Phone 7 and Expression Blend for Phone 7 will be free.
Take a look at the Windows 7 Jump Start on-line training while you’re waiting.
Labs and code can be found in the Training Kit.
Tim Anderson has two informative posts about Microsoft’s LightSwitch. I’ll try to summarize them here.
Ten things you need to know about LightSwitch (Tim Anderson):
Visual Studio LightSwitch – model-driven architecture for the mainstream (Tim Anderson):
Tim spoke to two LightSwitch team members. They couldn’t speculate on a release date, but did say that Windows Phone 7 will not be targeted in the first release. Perhaps it will be added later. The product was designed to allow different output formats for applications, but Mac is not considered high-priority. The development of LightSwitch had an influence on the design of some WCF RIA Services features.
While Microsoft seems to be positioning LightSwitch as a tool for the masses to develop departmental applications, it remains to be seen if it will catch on. Perhaps on a larger scale, Microsoft intends to deliver on the promise of model-driven application generation. And that would be no small feat.
Microsoft has released the first beta of its LightSwitch product.
LightSwitch allows you to create web-based data-driven applications, using industry-standard patterns and technologies: Entity Framework, WCF RIA Services and Silverlight.
More LightSwitch links:
What is WCF RIA Services? Well it is .NET RIA Service renamed, to more accurately represent the communications framework that is being used.
See: WCF RIA Services aka .NET RIA Services now available
The MSDN Doc page: http://msdn.microsoft.com/en-us/library/ee707344(VS.91).aspx
Get Started with WCF RIA Services: http://silverlight.net/getstarted/riaservices/
Get the news here: Silverlight 4 Beta : The Official Microsoft Silverlight Site
Silverlight 4 development will require Visual Studio 2010.
Visual Studio 2010 can be installed side-by-side with Visual Studio 2008 SP1. Please read the known issue on installing Visual Studio 2010 if you already have the Silverlight 3 SDK installed.
Silverlight 4 on MDSN: http://msdn.microsoft.com/en-us/library/cc838158(VS.96).aspx
What’s New (partial listing)
Printing (finally): Silverlight 4 adds printing support that allows developers to control whether their Silverlight application can print itself, how the content is formatted when printed, and determine the content that will appear. For example, you could add a print button to your Silverlight application that opens the Print dialog allows the user to choose the printer, and then prints the Silverlight content.
Implicit Styles: Silverlight 4 introduces new styling features that allow you to create a style as a resource that can be used implicitly by all elements of a target type. This allows application developers to customize the look across multiple instances of a control and modify the appearance of these control instances by changing the implicit style.
Right Mouse Click: Silverlight 4 adds the ability to right click a visual element to perform custom actions such as displaying a menu that provides contextual commands or invoking commands for a Silverlight game.
Programmatic Clipboard Access: Silverlight 4 adds the ability to programmatically access the clipboard to format and modify data during copy, cut, and paste operations. To copy data from a Silverlight application to the clipboard use the Clipboard.SetText method
Silverlight as a Drop Target: Silverlight 4 now supports being a drop-target for the common drag-and-drop practice of clicking on a virtual object and dragging it to a different location or onto another virtual object. Both Windows and Mac platforms support this feature. Silverlight only supports dragging of file(s) from local client and dropping them onto a Silverlight application. It does not support dragging of folders (directories).
ObservableCollection<T> Constructor Accepts IList and IEnumerable (yay!): Silverlight 4 also can take advantage of new constructor overloads that allow it to initialize an ObservableCollection<T> from an IEnumerable or IList.
More can be found on Tim Heuer’s blog: http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx
Brad Abrams announced last week that Microsoft has launched an official community site for RIA Services.
You will see that the latest version available of RIA Services is still the July 2009 CTP.
I expect to see a new release next week at PDC.
See Mary Jo Foley's piece here.
Also, tomorrow is the launch for SL3 and Expression 3. It starts at 10 AM PDT I am told - that's 1 PM on the East Coast.
Go to www.seethelight.com tomorrow to enjoy all the silvery goodness.
The ADO.NET team at Microsoft has released an update to EF since the Beta release of VS2010/Net4.
They are calling it Entity Framework Feature CTP 1. Some of these features are not scheduled to be in .NET 4 when it releases, so if you want them, download the CTP and give them feedback.
From InfoQ:
Microsoft announced System.Data.OracleClient will be deprecated after .NET 4.0. Classes in the namespace will be marked obsolete in .NET 4.0 and removed from future releases. OracleClient is the ADO.NET provider for Oracle developed by Microsoft and shipped as part of the .NET Framework Class Library.
Part of the reasoning for this decision is the increasingly availability and improvements of 3rd party ADO.NET data providers for Oracle. There have been significant performance improvements and enhanced multi-version compatibility among the popular Oracle providers:
- Oracle's free Oracle Data Provider for .NET (ODP.NET) ODP.NET 11g is compatbile with all versions of Oracle Database back to 9.2, and multiple versions can coexist in a single OS
- DataDirect ADO.NET Data Provider for Oracle 100% managed code, free trial
- Devart dotConnect for Oracle Formerly known of as OraDirect.NET, free trial, supports Entity Framework, LINQ to Oracle, and ASP.NET Provider Model
Rob Eisenberg has a blog post in which he details the important changes since the beta release of Caliburn.
What is Caliburn?
Caliburn is a toolkit to help you build Silverlight and WPF applications that are compliant with a number of UI design patterns (MVVM and Command Pattern being the relevant ones for me).
I’ve been working with Prism for a few weeks and now I have to figure out how to get Prism and Caliburn to play nice together.
Dinesh Kulkarni, from the RIA Services team, has published a roadmap for RIA Services. No guarantees here, but they hope to release a beta at PDC in November. The next CTP will be in July.
It's a bit disappointing to me. I had heard a rumor that RIA would release with Silverlight 3 in July. Perhaps it referred to the CTP. According to the roadmap, they are making changes to the underlying protocol (moving to ADO.NET Data Services), so you know that will take a lot of time.
Highlights from his post:
July 2009 CTP
This is a preview, not the V1 release. We plan to drop go-live restriction from EULA – still use it at your own risk.
Try to get significant known breaking changes (the ones we don’t know about will come later)
Feature enhancements (e.g. code-gen hookpoints to add your custom code, improved library support, better shared code support, query for singletons, cleaner user model and better extensibility support for Application Services etc.)
Usual fare of bug fixes, API improvements etc
Enable a first set of better together experiences with ADO.NET Data Services (add a DomainService to Data Service for writing app logic / expose DomainService as DataService)
PDC 2009 Beta
Additional core feature work (list TBD, under consideration – hierarchy support, presentation model)
Work on Visual Studio 2010 / .NET 4 support
Drag-drop support for databinding
Run in medium trust
Move to ADO.NET Data Services as the underlying protocol
First part of 2010: RTW
Polish beta release (bugs, perf, stress, security, localization, …)
Small design changes / tweaks
Keep up with changes in other products
A note on Platforms and tools
In each CTP, we will be keeping up with corresponding public Silverlight drops as and when they are scheduled (sorry, I don’t have that schedule)
For RTW, we are planning Visual Studio 2010 / .NET 4 as the primary story. Support for previous version TBD (depends on feedback about relative importance / cost / options)
Not according to Jesse Liberty.
You will want Blend 3 for its terrific designer and animation capabilities and VS for its development capabilities. Microsoft is trying to make these tools the best for their target audience, rather than one tool that does everything merely adequately.
The other point Jesse makes: Because it is a few months old at this point, the Blend 3 beta won't work with .NET 4 projects yet. If you want to work on projects in VS 2010 and Blend 3, create them as .NET 3.5 projects.
According to this post by Tim Heuer, the good news is that you can install the Silverlight 2 and 3 SDKs with Visual Studio 2010 Beta 1. You will get multi-targeted Silverlight development (i.e., either Silverlight 2 or 3) and an editable design surface.
Do not install the Silverlight 2 or 3 Tools packages, it won't work on VS 2010. And the Silverlight Navigation App template is not included with the SDK, only with the tools package.
You also need to install the Silverlight 3 Beta Developer runtime.
The bad news: .NET RIA Services will not install on VS 2010 Beta 1.