Meta data on table scaffolding in dynamic data project - entity-framework

I created an ASP.NET webapplication with dynamic data. I'm fairly new to this so I'm struggling with alot of things but now I'm completely stuck.
Thing is, I want to hide, lets say, the name column of a table in my database (model based on entity framework). Therefor I added a new folder named "AppCode" (because I cannot add the default app_code folder in a web app) and added a file named "User.cs" The contents of this file look like this:
[MetadataType(typeof(UserMetaData))]
public partial class User{
}
public class UserMetaData
{
[ScaffoldColumn(false)]
public object Name;
}
Now, after running the application I did not expect to see the name column in the crud pages, but it is still there. What am I missing here?
Thanks alot.

Finally figured it out myself. What went wrong was the fact that my model was placed in a referenced class library and not in the dynamic data project itself. It seems to be very important that the namespace of the partial class is the same as that of the model. Otherwise it would not work. So, in my case I had to place the partial class in my "domain" project which contains the model. Hope this helps someone.

Related

Entity Framework generated classes are not in the namespace I require, is there a way of changing the namespace it uses without regenerating?

If I need to regenerate where should the namespace be specified. I am trying to use partial classes from within the Models namespace however they don't match.
The simplified code fragment below is where the entity framework classes have been generated
namespace projectname
{
#region Contexts
/// <summary>
/// No Metadata Documentation available.
/// </summary>
public partial class MyClass
{
}
}
When I add a class to my models folder,
namespace projectname.Models
{
public partial class MyClass
{
//etc, etc
}
}
As you can see the namespaces don't match causing issues when I try and use them as the compiler is seeing both projectname.Models.MyClass and projectname.MyClass.
I would like some advice on the correct way to fix this, preferably to update the E.F. classes so they exist in the projectname.Models namespace, but I am not sure how to go about it.
In line with Roman O's comment, namespace can be changed by updating "Custom Tool Namespace" property of text transform (.tt) file, which ties generated entity classes (in Database First approach) to entity model (.edmx) file. This works in VS 2012 Express with EF 5.0.
I would post a screenshot but for lack of reputation.
IIRC, if you are using an Entity data model, you should be able to change the namespace directly through the xml file or files (you may have to change it for all the various storage and and conceptual models). There might even be some way to change it in the designer.. seems simple enough.
Actually, the solution might be here:
Generated Code Overview (Entity Data Model Designer) (see Custom Tool Namespace)
Right click the .edmx file in the project in Solution Explorer and select Properties
In the VS properties pane, fine Custom Tool Namespace
Enter the full CLR namespace you'd like
Rebuild the project
Namespace of auto-generated classes will be inherited from VS project settings (and even change if you change it there). Of course you should have "Custom Tool Namespace" property empty. (just tested it with VS2013 and EF6.1)
Unlike settings files which had always been pita :)
For older version there is a good video on manual changing :
https://youtu.be/B7Cqc9F0Ih8

Use T4 DBContext Script to Write Display Name Attribute

My issue is simple: the code I'm writing is in English, but the interface is in Portuguese. Not a problem, as I can do this:
[Display (Name = "Símbolo")]
public string Symbol { get; set; }
This way, when I render my screen, it comes in Portuguese:
#Html.LabelFor(model => model.Symbol)
But...
As I am using Model First EF for my project, classes are constantly been changed by a T4 DbContext Generator. That way I can't use Display attribute, as it will be overwrited.
A solution given here is to extend partial classes automatically created. Kinda clumsy for me.
So my idea is to change the T4 script to get Documentation.Summary attribute from the EDMX model and add it as a Display Name attribute.
I found an article where someone explains how to extract this data, but I'm not succeding in making it work on DbContext Generator.
Has someone ever made this? Do you guys have better ideas?
Thanks!

Helper properties from Entities in Silverlight client, shared code

I'm trying to figure out how to create additional "calculated" properties that are exposed in a Silverlight client for a given Entity type. My solution structure is as follows (Simplified):
Namespace "Data Access", Class Lib, that holds my EDMX
Namespace "Web" Web app that hosts the silverlight application as well as the Domain Service that projects over the EDMX (So it have a reference to the "Data Access" project.)
Namespace "SLApp", the Silverlight App
One of my entities is Person (very simplified):
public partial class Person
{
public string FirstName {get; set;}
public string LastName {get; set;}
}
I want to have a "helper"/"calculated" property called FullName that simply puts the first and the last names together. In the past this was easy; create my own public partial class Person class and add the property/logic and then I can just use it as as normal property. But the RIA Domain Service does not seems to expose that property, so I can't use it on the client. If the EDMX was in the Web application I could use the .Shared.cs file and have it included in the SL app (I guess) but I don't want my EDMX in the web app (feels dirty :) )
I'm using the MVVM pattern so I could just create the Property on the ViewModel class, but seems like I'd have to duplicate that logic a number of times (any ViewModel that I need the FullName property on). I tried creating an extension method for the Person Object in the SL App called FullName, but apparently you can't bind to extension methods.
I'm new to Silverlight this is my first "real" application so maybe I'm just missing something very simple... I hope I am. Any help would be great.
Thank you!
Have you added [DataMember] Attribute to your calculated property?
[DataMember]
public string FullName
{
get { return string.Format("{0} (1)", this.FirstName, this.LastName); }
}

RIAServices unsupported types on hand-built DomainService

My EF model was generated from my SQL Server database. I then generated a DomainService for RIAServices against the EF model. One of the entities is called "EntryCategories". The DomainService created this method:
public IQueryable<EntryCategories> GetEntryCategoriesSet()
{
return this.Context.EntryCategoriesSet;
}
Since my user interface display model looks quite different from the physical model, I decided to write my own DomainService for that and related entities. Yes, I know we are meant to modify the generated one but it has so much stuff in there and I wanted to focus on a small thing.
I removed the EnableClientAccess attribute from the generated DomainService and added a new class called ClientDomainService, and encapsulated in it the generated DomainService:
[EnableClientAccess()]
public class ClientDomainService : DomainService
{
// the generated domain service encapsulated in my new one.
private DataDomainService _dcds = new DataDomainService();
// reimplement one of the DataDomainService methods
public IQueryable<EntryCategories> GetEntryCategories()
{
return (from t in _dcds.GetEntryCategoriesSet() where t.EntryCategoriesVersions.EntryCategoriesVersionId == datahead.EntryCategoriesVersions.EntryCategoriesVersionId orderby t.DisplayOrder select t);
}
}
The very fist thing I tried is to reimplement the GetCateogoriesSet method but with the underlying data filtered based on another entity in my class (not shown). But when I build this, an error shows up:
Entity 'DataProject.Web.EntryCategories' has a property 'EntryCategoriesVersionsReference' with an unsupported type
If I comment out my CientDomainService, replace the EnableClientAccess attribute on the generated DomainService, and place the analagous linq filtering in the original GetEntryCategoriesSet method, the project compiles with no errors.
What is so special about the generated DomainService that my new one doesn't have? Is it that metadata.cs file?
What's special about the generated domain service is not the .metadata.cs file (you can keep it, and use it, but it doesn't solve your problem).
The problem appears somehow because RIA services (?) needs a 'domain service description provider' for the exposed Linq to EF entities. The LinqToEntitiesDomainService class has the LinqToEntitiesDomainServiceDescriptionProviderAttribute, already applied, so the generated domain services which inherit from it also inherit the provider.
When you build your own custom domain service, derived from DomainService, and expose entities through it, you need to apply this attribute yourself. Furthermore, since the provider cannot infer the object context type from the domain service base class (which it can and does if the base class is LinqToEntitiesDomainService), you need to specify the object context type in the attribute constructor, like this:
[EnableClientAccess()]
[LinqToEntitiesDomainServiceDescriptionProvider(
typeof(YourObjectContextType))]
public class ClientDomainService : DomainService
{
...
}
That should fix it.
Note that this means if you had hoped to abstract your object context away from your domain service, you'll be disappointed. I had opted for the seemingly popular repository model where all code that operates on the object context goes into a provider used by the domain service. This facilitates unit testing, but evidently doesn't remove the domain service's dependency on the object context. The context is required for RIA Services to make sense of your entites, or at least those referenced by the domain entity (such as EntryCategoriesVersions in your case).
If you want to expose a specific entity on a domain service you will have to provde at least one query method for it. This is also required when the entity is only accessed as a child of another entity.
In this case you need to add the EntryCategoriesVersions entityset to the domain service, to get the scenario working correctly.
What type is EntryCategoriesVersionsReference ? Try adding a [DataContract] annotation against the type, and appropriate [Key] and [DataMember]. It should help with marshalling.
For me, the fix for this error was to add a default constructor to the return type.
In OP's example, the property 'EntryCategories.EntryCategoriesVersionsReference' needs to be of a type with a default constructor.

How to save manual change after a update using Entity framework designer?

I'm using entity framework designer to build entities. I found the designer really hard to use because it overwrite all your manually change after each model update using the designer. How did you round off this problem? Thanks!
What sorts of things are you manually changing? The entity still has to be mappable to the database schema.
You can extend or add functionality by declaring a partial class.
Don't make any change to the entities in the generated file -- I think it says that in the header.
All of the entities are generated as partial classes, which means you can declare "more" of the class elsewhere.
Here is an example:
public partial class Name
{
public string First { get; set; }
}
public partial class Name
{
public string Last { get; set; }
}
Although I have two different class declarations, potentially in different files and folders within the project, it gets compiled as one class.
I can now use the Name class like this:
var name = new Name();
name.First = "Jane";
name.Last = "Doe";
As you can see, the properties from both declarations are unified in an object of type Name.
To apply this to EF, leave the partial entity class alone, and declare a separate partial class with the same name to add functionality.
There is an alternative third-party tool. For more information, refer this. Currently, Devart Entity Developer doesn't include the Update From Database functionality. The Update From Database feature is on our roadmap.