Feature CTP Walkthrough: Self Tracking Entities for the Entity Framework

Published 22 June 09 02:08 PM | dpblogs 

Start

For the sake of brevity we are going to start with a prebuilt Visual Studio solution. The solution is a simple WCF service for Blogging, and contains three projects:

  • BloggingModel: this is a class library containing an entity model created using the EDM designer.
  • BloggingService: this is the WCF service application itself, contains the definition of the service contract and some code for the service.
  • BloggingConsole: this is a simple console application structured as a series of simple tests for the service.

To start, open the EDM model named Blogging.edmx that is included in the BlogginModel project.

Adding Templates

The first step is going to be to add T4 templates for generating the self tracking entities. In order to do that, you will open the Blogging.edmx model contained in the BloggingModel project.

blog1

From any blank area in the surface of the EDM designer, right click and select the “Add New Artifact Generation Item…”

blog1 
This will display a standard “Add New Item” dialog. Select the item type “EntityFramework SelfTracking code generator”, specify “Blogging.tt” as the name, and click on Add.

blog1

Note: As soon as the template files are added to the project, a security warning will pop up asking you to accept only if you trust the source of the template. Accept in order to continue with this walkthrough.

Notice that the BlogginModel project now contains two TT files: Blogging.Types.tt and Blogging.Context.tt.

What has just happened? When you add T4 templates for code generation like this, the default code generation used for Entity Framework models is turned off and the T4 templates take over that responsibility. T4 is a powerful code-generation tool included in Visual Studio. T4 templates can be modified by users to produce different code patterns based on the same input. To learn more about T4, you can visit this link.

Shared entity types

While self tracking entities code is generated automatically, the feature takes advantage of the new support for Persistence Ignorance in Entity Framework, and therefore the code generated is quite simple. You can browse the code files generated under Blogging.Types.tt to get an idea of what it involves.

As an example, the following code represents the public interface of the Person entity (not the complete source code):

[DataContract(IsReference = true)]
[KnownType(typeof(Entry))]
[KnownType(typeof(Blog))]
public partial class Person: IObjectWithChangeTracker
{

public Person();

[DataMember]
public int ID {get; set; }

[DataMember]
public string Firstname {get; set; }

[DataMember]
public string Surname {get; set; }

[DataMember]
public string EmailAddress {get; set; }

[DataMember]
public virtual FixupChangeTrackingCollection<Person, Entry> Entries {get; set; }

[DataMember]
public virtual FixupChangeTrackingCollection<Person, Blog> Blogs {get; set; }

public void MarkAsDeleted();

public void MarkAsAdded();

public void MarkAsModified();

public void MarkAsUnchanged();

[DataMember]
public ObjectChangeTracker ChangeTracker {get; set; }

}

A few things to observe in this code:

  1. The DataContract has IsRefernece = true: this allows WCF to serialize bidirectional graphs with cycles.
  2. All properties are marked as DataMember.
  3. FixupChangeTrackingCollection is a collection type that is also included in code generation that besides being able to store information about changes, provides the capability to align both sides of a relationship. For instance, when a Blog is added to a Person’s Blogs collection, the Blog’s Owner reference is also updated to point to the right Person.
  4. The methods called MarkAsDeleted, MarkAsModified, MarkAsAdded and MarkAsUnchanged can be used to manually control the state of individual entities. There are other, more implicit ways to establish the state of an entity: entities that are tracking are also automatically marked as Modified when a property value is modified. When adding a new entity to a collection in another tracking entity, the new entity will become Added.
  5. The ObjectChangeTracker property provides public access to the data structures used for change tracking.

The main goal behind designing self tracking entities as POCO classes is that they don’t require Entity Framework to be used on the client computer in distributed scenarios. In order to facilitate working with self tracking entities when they are serialized on the client, we are going to share the code for the types themselves between the service and the client.

Potentially, we could adapt self tracking entities to work with versions of the CLR that do not contain Entity Framework at all, such as Silverlight 3.

Note: The self tracking entity types generated by the T4 template included in the Entity Framework Feature CTP1 use attributes not present in the version of WCF included in Silverlight 2, like the OnDeserialized attribute. It is our goal to achieve compatibility with at least some version of Silverlight in the next release of the Feature CTP.

In order to get closer to this goal, as part of this walkthrough we are going to move the code generated for entity types (under Blogging.Types.tt) and the code that is part of the persistence layer (under Blogging.Context.tt) into separate assemblies.

As a first step, we are going to turn off code generation for the templates inside BloggingModel.

Select the Blogging.Types.tt file on the Solution Explorer. You should be able to see a property named “Custom Tool” in the Properties window (press F4 if the Properties window is not visible).

blog1

Remove the value from “Custom Tool” (“TextTemplatingFileGenerator”) and leave it blank. Also, notice that generated files (i.e. CS files) under this template are not removed automatically. You will need to expand the tree of generated files under the template and delete them.

 

blog1

Then, repeat the operation with Blogging.Context.tt: remove the Custom Tool value and manually delete all related files.

We are now going to need a new class library to accommodate the entity types. Right click on the solution and add a new class library project using Visual Studio and name it BloggingEntities.

blog1

Note: You can remove the default Class1.cs file that is automatically added to the project.

Next, we are going to add the template for types to the new BloggingEntities project. Right click on the BloggingEntities project and select “Add | Existing Item…”.

Browse for files in the BloggingModel project (you may need to go one level up to see it, and then specify All Files (*.*) as the filter).

blog1

Select Blogging.Types.tt in the dialog, and on the drop down button at the bottom of the dialog, select the option “Add As Link”.
blog1

When you add an item to a project as a link, the actual contents of the item are maintained in the location indicated by the original project (this is important because the TT file needs to be alongside the EDMX file in order to take it as input), but contribute generated code files to the current project. Since the link is specified using relative paths, the position is preserved if you move the solution to another directory or in source control.

blog1

If you try compiling the BloggingEntities project now, you will see a big number of errors. The reason is that self tracking entities use DataContract attributes defined in the WCF libraries, which are not referenced by default. Add a reference to the System.Runtime.Serialization library as shown below:

blog1

Service project

The initial version of the service project contains the service interface definition and basic code for the service implementation. We will be completing and removing commented lines from different parts of the source code until we have a functional WCF service.

blog1

The three first things the service is going to need are:

  1. The EDM metadata for the Blogging model.
  2. The CLR types for the entities.
  3. The code for the persistence layer (for the sake of brevity we are not going to create a separate assembly for the persistence layer, nor a full blown Repository abstraction).

Metadata

Since the BloggingModel project contains the EDMX file, the output assembly will contain the necessary metadata as embedded resources. In order to make the metadata available to the service, we can simply add a project reference on BloggingService pointing to BloggingModel.

blog1

For the Entity Framework runtime to find the metadata, it is necessary to provide the location (in this case a path that points to the embedded resources) in the connection string. An appropriate connection string is already included in the service’s web.config file:

<connectionStrings>
<add name="BloggingContainer" connectionString=
"metadata=res://*/Blogging.csdl|res://*/Blogging.ssdl|res://*/Blogging.msl; provider=System.Data.SqlClient;provider connection string=&quot;
Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Blogging.mdf;
Integrated Security=True;User Instance=True;MultipleActiveResultSets=True&quot;"
providerName="System.Data.EntityClient" />
</connectionStrings>

Entity Types

As explained previously, we are going to share the entity types between the service and the client. We do that by adding a reference to the BloggingEntities model.

blog1

Persistence layer

The persistence layer is going to be composed of the ObjectContext type generated by the Blogging.Context.tt file. Add a link to Blogging.Context.tt on the BloggingService project following the same procedure we used previously to add a link to the Blogging.Types.tt template to the BloggingEntities project.

blog1

As before, remember to add it as a link:

blog1

Important: Also, in order to get the namespace of the code generated by this template to match the namespace of the code generated by the Blogging.Types.tt template, we will need to set the value of the “Custom Tool Namespace” to “BloggingEntities”.

blog1

Service interface

The service interface is contained in the IBlogging.cs file. The interface defines four methods:

  1. Post GetPostWithComments(int PostID): retrieves a Post object by ID, including all the Comments related to that post.
  2. Void UpdatePostWithComments(Post post): provides the capability of persisting changes to a particular post, including a collection of its related Comment objects.
  3. GetATestPostID: retrieves an arbitrary PostID existing in the database for testing purposes.
  4. GetATestPersonID: retrieves an arbitrary PersonID from the database for testing purposes.

To continue with the walkthrough, un-comment the code contained in IBlogging.cs.

Service Implementation

The service implementation is contained in the Blogging.svc.cs file. GetPostWithComments, GetATestPostID and GetATestPersonID are just regular methods that return results of a query through the service operations. The only thing new about these methods with respect to something you could do previously with Entity Framework is that they now return graphs of self-tracking entities.

We are now going to focus on the most interesting operation, UpdatePostWithComments, which leverages self tracking entities in order to persist changes that have happened to the object graph on the client.

In order to proceed, uncomment the four public methods of the Blogging.svc file.

UpdatePostWithComments

This method takes a post self tracking entity, passes it through to validation logic, and then applies the changes contained in the object graph to the ObjectContext. Finally, it tries to save the changes.

public void UpdatePostWithComments(Post post)
{
ValidateUpdate(post);
ApplyDefaults(post);
using (var context = new BloggingContainer())
{
context.Entries.ApplyChanges(
post,
EntityChangeTrackerAdapter.GetSelfTrackingEntityInfo);
context.SaveChanges();
}
}

 

 

At the core of UpdatePostWithComments, we are using the ApplyChanges extension method that the Feature CTP components define on ObjectSet. The goal of ApplyChanges is to retrieve changes made to the graph of self tracking entities and infer, and reproduce all those changes on a regular ObjectContext and ObjectStateManager, so that the Entity Framework update components can store those changes to the database.

The method takes two parameters:

  1. The root object of the graph of self tracking entities
  2. A delegate type that takes an entity and returns an instance of the IEntityChangeTracker interface.

The delegate passed to the ApplyChanges method is an adapter that takes self tracking entities and returns a data structure that ApplyChanges can understand. The reason we define such an adapter interface is that we wanted self tracking entities to not have a dependency on Entity Framework.

EntityChangeTrackerAdapter.GetSelfTrackingEntityInfo simply returns an implementation of this adapter that is tailored for the entity types generated by our T4 template.

You would need to provide an adapter that complies with the same interface if, for instance, you wanted to write your own blend of self tracking entities that work with ApplyChanges.

Validation and Defaults

When creating a public facing service that takes client inputs, you should always validate those inputs. For that reason, the sample in this walkthrough demonstrates how to perform some basic validation that restricts the kind of changes that the self tracking entities can perform.

In order to enable this, uncomment the ValidateUpdate method.

private static void ValidateUpdate(Post post)
{
ValidateCondition(
post.ChangeTracker.State != ObjectState.Deleted,
"Deleting a post is not allowed");
ValidateCondition(
post.ChangeTracker.State != ObjectState.Added,
"Adding a post is not allowed");
ValidateCondition(
post.ChangeTracker.State == ObjectState.Unchanged ||
!string.IsNullOrEmpty(post.Body),
"Empty posts are not allowed");
ValidateCondition(
post.ChangeTracker.State == ObjectState.Unchanged ||
!string.IsNullOrEmpty(post.Title) ,
"Empty posts titles are not allowed");
ValidateCondition(
!post.Comments.Any(c => c.ChangeTracker.State != ObjectState.Unchanged &&
string.IsNullOrEmpty(c.Body)),
"Empty comments are not allowed");
ValidateCondition(
!post.Comments.Any(c => c.ChangeTracker.State != ObjectState.Unchanged &&
string.IsNullOrEmpty(c.Title) ),
"Empty comment titles are not allowed");
}

Essentially, this method throws an exception if any of the following conditions occur:

  1. The blog post contains an empty body or title.
  2. Any of the comments contain an empty body or title.
  3. The client is trying to add a new post or delete an existing post (the UpdatePostWithComments operation was only designed to perform updates on posts).

The next method invoked by UpdatePostWithComments is ApplyDefaults, which sets the ModifiedDate and CreatedDate on Posts and Comments as appropriate. This kind of method is useful if you expect client code not to do that part of the work.

private void ApplyDefaults(Post post)
{
var now = DateTime.Now;
post.ModifiedDate = now;
foreach (var comment in post.Comments)
{
switch (comment.ChangeTracker.State)
{
case ObjectState.Added:
comment.CreatedDate = now;
comment.ModifiedDate = now;
break;
case ObjectState.Modified:
comment.ModifiedDate = now;
break;
}
}
}

The Client

Included in the solution, there is a very simple console application that is used to test operations on the service. The BloggingConsole project will need two things to operate:

1. CLR types for entities.

2. A service reference to BloggingService.

It is worth mentioning that the client doesn’t need EDM metadata.

Entity types

The same way we did it on BloggingService, we can just add a project reference to BloggingEntities in order to get the definition of the types on the client.

blog1

Service Reference

Before you can actually add the service reference, you will need to make sure the service project is built. Otherwise, WCF design-time tools will fail to obtain the service’s metadata. Right click on the BloggingService project entry in the Solution explorer and choose the Build menu item.

Once built, you can proceed to add a standard Service Reference to BloggingService on the BloggingConsole project:

blog1

When configuring the service reference, specify BloggingService as the namespace. You will need to use the Discover button to find the service exposed by the BloggingService in the same solution.

blog1

Since the types of the entities are already known, WCF design-time tools will only add the minimum code necessary for the service interface and for the service client.

Client tests

In order to proceed, uncomment the methods on Progam.cs, which contains some simple scenario test for the service. The program follows this sequence:

  1. An existing PostID and a PersonID are obtained from the service.
  2. Retrieve the post corresponding with PostID.
  3. Add a new comment to the post, and save it through the UpdatePostWithComments service operation. The author for the comment is the person corresponding to PersonID.
  4. Delete all comments for the post and persist this change through the UpdatePostWithComments.
  5. Also, the post is retrieved and displayed in the console at various stages.

Notice that each separate method creates and disposes its own instance of the service client, just for the purpose of testing operations independently.

The most interesting method here is AddComment:

private static void AddComment(int postID, int authorID, string title, string body)
{
using (var service = new BloggingClient())
{
var post = service.GetPostWithComments(postID);
var author = new Person { ID = authorID };
post.Comments.Add(new Comment { Author = author, Title = title, Body = body });
service.UpdatePostWithComments(post);
}
}

The method follows this sequence:

  1. Creates an instance of the service client within a using statement.
  2. Retrieves a blog post from the service using GetPostWithComments.
  3. Create a new Person entity called author. This entity is a “stub”, since it is only going to hold the key.
  4. Add a new Comment to the Post, by filling the author, title, and body.
  5. Send the proposed change to the service through UpdatePostWithComments.

Another interesting method to observe is DeleteAllComments:

private static void DeleteAllComments(int postID)
{
using (var service = new BloggingClient())
{
var post = service.GetPostWithComments(postID);
foreach (var comments in post.Comments.ToArray())
{
comments.MarkAsDeleted();
}
service.UpdatePostWithComments(post);
}
}

The method follows this sequence:

  1. Creates an instance of the service client within a using statement.
  2. Retrieves a blog post from the service using GetPostWithComments.
  3. Marks each comment for the post as Deleted.

Notice that the foreach loop is performed over a copy of the original collection of comments. This has to be the case because MarkAsDeleted will remove the entity from the collection, and modifying the enumeration over which foreach is looping would cause an exception.

If you want to test how the service validation works, you can try passing an empty string for title or the body of a comment, by adding a line like this:

AddComment(postID, authorID, "Bad post", "");

Final stop

You can learn a lot more about self tracking entities while executing and stepping through this sample program. Before starting it, make sure the BloggingConsole project is the start up project by right clicking on the project entry on the Solution Explorer and then choosing the “Set as StartUp Project” menu item.

Here is the default output of the program:

blog1

The walkthrough has described some basic usage of self tracking entities. We hope you have learned enough about how to use self tracking entities that you can experiment with the Feature CTP1 version on your own code.

There are many areas in which we expect to be improving self-tracking entities in the next release of the Entity Framework Feature CTP. Please let us know of any issues you find.

Notes

Why not POCO Proxies

Alongside POCO support, we added the capability to create dynamic proxies for entities that comply with certain requirements. Self tracking entities do not make use of this feature for several reasons:

1. Self tracking entities are optimized for serialization scenarios, and dynamic proxy types complicate WCF serialization. Before serializing, we would need to take advantage of WCF interception mechanisms to “convert” the instance to serialize back to the original POCO types.

2. One of the characteristics of POCO Proxies is their ability to perform lazy loading. Using serialization and lazy loading together requires much care, since lazy loading may cause unintended data to be queried and included in the graph.

3. In the main scenario we are trying to address in this release, most changes happen on the client side. While change tracking proxies optimize change tracking performance, that only happens when the entities are being tracked by the ObjectStateManager. The default snapshot-based change tracking mechanism used for pure POCO objects provides enough functionality for self tracking entities.

Database generation scripts

If you need to create the database outside the project, you will find database creation scripts in the App_Data folder of the BloggingService project.

- Diego Vega
  Program Manager, Entity Framework

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# DotNetShoutout said on June 23, 2009 6:27 AM:

Thank you for submitting this cool story - Trackback from DotNetShoutout

# leftside said on June 23, 2009 5:14 PM:

Very nice walkthrough. Do you have a similar one for ASP.NET?

# Manfred said on July 8, 2009 8:03 PM:

Hi,

I've tried this out -- without success. I'm using the current BETA of VS2010 and EF4FeatureCTP1.exe.

What could I've done wrong?

Regards,

Manfred

   public class CategoryDAO

   {

       public Category findById(int id)

       {

           using (ProductDBEntities e = new ProductDBEntities())

           {

              return e.Categories

                   .Include("Products")

                   .Where(c => c.CID == id)

                   .First();

           }

       }

       public void update(Category c)

       {

           using (ProductDBEntities e = new ProductDBEntities())

           {

               e.Categories.ApplyChanges(c, EntityChangeTrackerAdapter.GetSelfTrackingEntityInfo);

               e.SaveChanges();

           }

       }

   }

[...]

       static void Main(string[] args)

       {

           CategoryDAO dao = new CategoryDAO();

           Category c = dao.findById(1);

           Console.WriteLine(c.Name);

           foreach (Product p in c.Products.ToArray())

           {

               Console.WriteLine(" > " + p.Name);

               p.MarkAsDeleted();

           }

           Product prod = new Product()

           {

               ID = 10,

               Name = "Test!"

           };

           c.Products.Add(prod);

           dao.update(c);

           Console.ReadLine();

       }

# Krishnamurthy said on July 13, 2009 10:50 AM:

I tried to add the new item (the very first task in the walkthrough), but the add new items has only the ADO.NET EntityObject Generator template. Why do I have templates missing in VS 2010? How can I get this template?

# Krishnamurthy said on July 13, 2009 10:56 AM:

My apologies, I realized I hadn't installed the feature CTP.

# Steve M said on July 14, 2009 4:39 PM:

Is it safe to assume there won't be a change tracking solution that is interoperable with non-clr technologies in EF 4.0?  An example would be serializing to JSON for use with the new Ajax features in asp.net 4.0, or even when consuming these services through Java or AS3.

Everything in the EF 4.0 has been really impressive thus far, but losing interoperability(one of the main advantages of using web services in the first place in my opinion) would be unfortunate.

Regardless, thanks for all the updates, they're very helpful.

# Diego Vega said on July 21, 2009 11:33 AM:

@Steve: While we haven't attempted to provide an end to end solution in which the client runs in JavaScript or on some other platform, it is one of our design goals to keep the “public surface”  of self-tracking entities as simple as possible to enable other implementations:

- On one side, the serialization payload that is produced with the classes we generate is very clean and I can imagine it would be possible to consume and produce it relatively easily from any client.

- On the other side, if you want to provide your own entity types and serialization, you can think of implementing the adapter interface that the ApplyChanges method takes as the second parameter.

Given the current implementation, however, if you just wanted to directly use JSON, there is a known issue with DataContract’s IsReference = true. We will keep these things in mind for our next refresh.

# Zubin said on July 21, 2009 2:24 PM:

Manfred,

I noticed that you are not using WCF, all operations are happening on the server side. In this case, you must turn on ChangeTracking manually in your main() after retrieval:

Category c = dao.findById(1);                                c.ChangeTracker.ChangeTrackingEnabled = true;

Note that if your dao actually go through WCF serialization, ChangeTracking will be turned on by default.

# Martin said on July 22, 2009 8:49 AM:

Once I move Blogging.Types.tt to BloggingEntities, I don't get generated files underneath it.

It has been added as a link

I've tried build and RunCustomTool.  The latter produces nothing in the output window either?? It's configured as TextTemplatingFileGenerator.  Custom Tool Namespace was blank - I made it BloggingEntities

The Blogging.Context.tt in BloggingService does work

Any ideas?

Thanks

Martin

# Martin said on July 22, 2009 12:11 PM:

I notice the final step version of the project (which does work) shows the generated files as linked.

Back to the initial project - if I click the "transform all templates" button

I get

Transforming templates for all project items.

-------------------------------------

Transforming template Blogging.Context.tt with TextTemplatingFileGenerator ... succeeded.

Transforming template Blogging.Types.tt with TextTemplatingFileGenerator ... succeeded.

-------------------------------------

Text templating transformation complete

In fact the files have been generated (in the same directory as the corresponding tt file). They just aren't linked in for the types tt file.  I don't know why they link ok for the context tt file.

Martin

# cowgaR said on July 25, 2009 11:07 AM:

I'm new to change-tracking entities, but...

should I understand that we never ever get lazy-loading with change tracking entities? So everything will be eager loaded? (I think there is lazy load in LLBLGen pro)

or we just don't get lazy loading in the - say - UI/Application layer, which is used for serialization to/from JSON, but once we have real object (deserialized) we can get lazy loading from our repositories, or can't we at all?

my head is dizzled but I am thinking about IQueryable repositories (although it is a bit different thing) and got an idea that they would not work without lazy loading being implemented here (e.g. I want to run queries on the sql server not in a memory and I don't want to have 200 methods in my repository class).

thanks for claryfing that, still thinking if there is the need to know whole object graph I am going to work with (hence UpdatePostWithComments) or there would be some improvements for developer not to think much about it (as these entities tend to be really cycled all over with another entities) as this way it is really dangerous not to think what I really need and all the time working with big object graphs.

once again thanks for answer, some mvc-ajax-serializing post would be welcomed though

# Ken Smith said on July 28, 2009 3:10 PM:

It looks like the process you're recommending requires the use of CLR types on the client.  How are you recommending that we use this approach with Silverlight clients?  I suppose we can implement our own tracking from scratch (as you seemed to recommend above), but that doesn't seem to be terribly efficient, and it certainly makes Silverlight a second-class citizen relative to the rest of the MS universe.  Are you planning to include self-tracking entity generation with the SLSvcInst.exe proxy generation tool?

# juanfbp said on July 28, 2009 4:16 PM:

Hi Diego,

Can you provide us a link to download this solution. ?

# Todd B said on July 29, 2009 11:40 AM:

I've noticed that with the Self Tracking Entities, when the ObjectContext's SavingChanges event is fired, the ObjectStateManager.GetObjectStateEntriesObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Modified) returns an empty list when there are modifications that actually do get persisted.  I want to be able to trap whenever and however an Entity is being saved. Is there another method I can employ to do this with the Self Tracking Entities?

Thanks.

# divega said on July 29, 2009 12:27 PM:

@Todd: Please, try invoking the context's DetectChanges() method before GetObjectStateEntries(). Self tracking entities are POCO objects without change notification, therefore it is necessary to push the changes from the object graph to the ObjectStateManager before invoking any API that requires having the ObjectStateManaer up to date.

# divega said on July 29, 2009 12:31 PM:

@Juan: the link for the walkthrough appears only in the abstract version of the post. I will see what we can do to have it also here. Here is the url in the meanwhile:

http://blogs.msdn.com/adonet/attachment/9798233.ashx

# juanfbp said on July 29, 2009 12:50 PM:

Thanks Diego!

I've replied your answer in:

http://social.msdn.microsoft.com/Forums/en-US/adonetefx/threads

(the Serializing self-tracking entities to byte array thread).

, I also provide a link to download my solution with the projects. Hope you can take a look at it and see why it's throwing that exception.

Thanks again.

# divega said on July 29, 2009 1:01 PM:

@Ken: tracking of changes on the client depends on the change tracking logic embeded in the entity types. Our current impementation has a couple of source code incompatibilities with the Silverlight version of the CLR and BCL, but we will work on that. We don't have plans to generate self-tracking entities as the default for WCF clients.

Also, if you need a rich application framework for Silverlight that works with Entity Framework, you may want to try .NET RIA Services.

# divega said on July 29, 2009 2:26 PM:

@Martin: Yes, the way I did the walkthrough I basically leave the original copy of the TT files in the same project as the EDMX file because the TT file needs to find the EDMX file in a relative path (although you can override the exact location by editing the TT file). Then I "add as linked" the TT files wherever I need them and that should automatically bring the linked generated files. I am not sure what can go wrong, but I guess my first recommendation if that doesn't happen is to revert things to the previous step (i.e. remove the linked TT file) and add it again.

Hope this helps,

Diego

# ncloud said on August 4, 2009 11:27 AM:

Hi, I'm trying to persist an object graph across the service.  The object graph looks like this:

Course

|- Professor Professor

|- List<Student> Students

When I change the Professor through databinding in WPF, the Course.ChangeTracker contains a reference to the original Professor in the OriginalValuesForReferenceProperties collection.  I use the ApplyChanges() method on the data context service side, and the first update works fine.  But if I change the Professor again, the SaveChanges() method of the data context says there is a duplicate key.  The Course.ChangeTracker also still maintains its original reference to the first Professor, which I am assuming is causing the duplicate key violation, but I can't seem to reset the ChangeTracker client side.  If I call Course.MarkAsUnchanged() on the client, the old Professor reference still remains.  My service call returns void, just like the examples above... but I've seen other people returning the same object after the database update.  Anyone having similar problems?

# divega said on August 9, 2009 3:12 AM:

@ncloud: can you please explain what do you mean with "if I change the Professor again"?

# uns_uwe said on August 15, 2009 9:34 AM:

Hi,

really a great Job!

I start to use this functionality for a new application!

Stay tuned!!!

Uwe

# dz said on September 14, 2009 3:29 PM:

i can't get it work for me.

I gave two related tables: Product and ProductCategory, and three WCF methods: GetProduct, GetCategory and UpdateProduct. If i'm changing simple properties of Product, it works fine, but if i'm assigning like this:

product.ProductCategory = wcfClient.GetCategory(catId)

and call UpdateProduct, it throws exception. From other side it doesn't work either, if I'm doing like productCategory.Products.Add(product) and call product category update, it falls with exception also.

# platon said on October 19, 2009 5:27 PM:

Hi, thanks for the article!

I have been having issues with "Unable to load the specified metadata resource" error. I have the following setup (just two tier)

Project 1: EntityModel (contains the edmx file with Embed in Output Assembly for the Metadat Artifact Processing)

Project 2: EntityTypes (contains EntityModel.Types.tt)

Project 3: DataAccess (contains EntityModel.Context.tt) and references EntityModel project.

Project 4: ConsoleApp (calls a DataAccess static method which instantiates the EntityContext).

The config file looks like this:

 <connectionStrings>

   <add name="EntityContext" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=TEST;Initial Catalog=test;Persist Security Info=True;User ID=sa;Password=test;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

 </connectionStrings>

When I instantiate the EntityContext in the DataAccess, I get the following exception:

"Unable to load the specified metadata resource".

I found that the EntityModel assembly is not loaded. After loading it explicitely from the DataAccess things work fine.

I would appreciate if anyone has suggestions. Loading assembly explicitely seems like a hack to me.

Thanks a lot.

# uns_uwe said on October 20, 2009 9:56 AM:

Hi,

is this functionality still available under Beta2 and later in the final release?

Thanks a lot!

# Júlio said on November 4, 2009 11:12 AM:

One question, i have a web service that return a System.Data.Entity.DynamicProxies and occur error this class is not serializable, what i can do????

# divega said on November 6, 2009 1:02 PM:

Hi Julio,

I think I already responded to you in the forums, but for the benefit of others that might hit this page: this is a known issue. The solution is not included in beta 2, but he workaround is to temporarily disable the creation of proxies when you are returning entities that you plan to return from the service. Use context.ContextOptions.ProxyCreationEnabled = false.

Hope this helps,

Diego

# divega said on November 6, 2009 1:04 PM:

@uns_uwe: Hi, an updated version of the CTP that is compatible with beta 2 has been released. You can find the announcement here:

http://blogs.msdn.com/adonet/archive/2009/11/04/ado-net-entity-framework-community-technology-preview-released.aspx

# Steve said on November 8, 2009 12:59 PM:

How do I create self-tracking poco objects.

I can only select one of the two templates.

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required

Search

This Blog

Syndication

Page view tracker