Поделиться через


Pluralization

Unfortunately in the current version of the Entity Framework, which ships in .NET 3.5 SP1, we don't make any attempt to Singularize or Pluralize names when reverse engineering a model from the database.

So if, for example, your database has a table called Orders you will get an EntityType called Orders too, which clearly doesn't make for the most read-able code:

Orders order = new Orders(); //? why not just Order ?

LINQ to SQL does a better job here, because it ships with simple but effective pluralization and singuralization services, that for the most part produces names you would expect.

Unfortunately the lack of a similar feature in the Entity Framework, means that generally the first thing you do after you've reverse engineered a model with the Entity Framework is fix-up all the silly names.

Now from the perspective of someone who delivers plenty of Entity Framework demos, this is quite embarrassing! 

But of course the real problem here is that it is time consuming and error prone for all but the most trivial models.

Solution:

In the next version we have added basic pluralization support. This support only really handles English, and here's why:

  1. Creating language and culture aware services is very hard, and we thought it would be better to spend our time working on the core of the Entity Framework.
  2. These sort of services are very general and as such we think that they belong elsewhere, maybe inside Windows itself?
  3. We have made the PluralizationService class public so you are free to write your own.

Our default English language pluralization is then used whenever you generate a model from a database or visa-versa (see model first) to help produce appropriate names.

And for command line users familiar with EdmGen.exe there is a new /pluralize switch also.

Basic Pluralization Rules:

So how does the Entity Framework use this pluralization service?

Well it calls the service to:

  • Singularize EntityType names
  • Singularize NavigationProperty names that point to 0-1 entities
  • Pluralize EntitySet names
  • Pluralize NavigationProperty names that point to 0-* entities

It turns out that if you do this, you get the model you are looking for most of the time.

The Pluralization APIs:

So far we've talked about default behavior, if however you need more control, for example if you want to specify custom pluralization rules or a create a completely custom service, you have to drop down to the API level.

Everything revolves around a newly added public PluralizationService class that looks something like this:

public abstract class PluralizationService
{
        public static PluralizationService CreateService(CultureInfo culture);

        public abstract string Pluralize(string word);
        public abstract string Singularize(string word);
}

As you can see classes that derive from PluralizationService can singularize and pluralize words.

You can also ask the PluralizationService to create a concrete PluralizationService for you based on Culture (as mentioned previously only "en" based cultures are supported out of the box).

Here is a little code that gets hold of the built-in English Language pluralization services, configures it so "Child" will pluralize to "Children" and then checks that it pluralizes correctly.

PluralizationService pluralizationService = 
PluralizationService.CreateService(
new CultureInfo("en-US"));

ICustomPluralizationMapping mapping =
pluralizationService as ICustomPluralizationMapping;

if (mapping != null) // it shouldn't be but just checking
{
    //Specifying the child pluralizes as children
mapping.Add("Child", "Children");
}

Debug.Assert(pluralizationService.Pluralize("Child") == "Children");

You can use your pluralization service in Model Generation (i.e. the step that produces CSDL and MSL from SSDL) by handing your pluralization service to the EntitySchemaModelGenerator:

//Create an EDM from SSDL generator
EntityModelSchemaGenerator generator =
    new EntityModelSchemaGenerator(
storageModel,
"MyNamespace",
"MyContainer",
pluralizationService);

//Generate CSDL and MSL (in memory)
generator.GenerateMetadata();

The resulting CSDL will have been pluralized/singularized as described in the earlier rules using the provided pluralization service.

See this for more information on the EntityModelSchemaGenerator.

Summary

So as you can see we've added simple pluralization capabilities, akin to those found in LINQ to SQL, that will reduce the amount of work required to create meaningful models.

And to top it off, the solution we've created is easy to customize and public so you can probably use this for other things too!

As always we are very keen to hear what you think.

Alex James
Program Manager
Microsoft

UPDATE:  A number of people have asked whether pluralization can be turned off, because the post doesn't make this clear. The answer is absolutely, pluralization is definitely optional, in Visual Studio this is as simple as checking/unchecking a checkbox in the wizard, and for EDMGen.exe you have to opt-in for pluralization with the  /pluralize commandline switch. 

This post is part of the transparent design exercise in the Entity Framework Team. To understand how it works and how your feedback will be used please look at this post .

Comments

  • Anonymous
    December 02, 2008
    The comment has been removed

  • Anonymous
    December 02, 2008
    Would be nice to have ability to turn pluralization off. If we do not plan to write our custom pluralization service and we use language other than English, then it's really annoying to end up with words that makes no sense (when pluralization is applied to a foreign language). This happens right now with Linq to Sql.

  • Anonymous
    December 02, 2008
    The comment has been removed

  • Anonymous
    December 02, 2008
    @Jon Glad you think this is a good thing to do. @Mifko Don't worry you will definitely be able to turn pluralization off, in Visual Studio there will be a checkbox in the wizard, and for EDMGen.exe on the commandline the default is not to pluralize you have to use the /Pluralize commandline switch to get pluralization.

  • Anonymous
    December 02, 2008
    I think it's very helpful, thanks.

  • Anonymous
    December 02, 2008
    Bear in mind when designing these pluralization/singularization methods that not everyone is using English names, and the rules for English do NOT apply for other languages (e.g. German, French etc.). The Linq-to-Sql method works pretty badly on German table names, and I'd STRONGLY argue that any such "automagic" feature needs to be able to turned off when it causes more grief than good.... What I'd really like to see in EF v2 is a way to specify certain "name transformations" when importing database tables - e.g. our DBA prefixes all tables with "T_" , e.g. T_Orders, so I'd like to be able to tell the EF designer to always remove a leading "T_" (or tbl) prefix from the physical database table name when creating an entity from it. With 3 or 4 tables, it's no trouble doing this manually - but what if you need to import hundreds of tables, and you need to later update that model???

  • Anonymous
    December 02, 2008
    The comment has been removed

  • Anonymous
    December 03, 2008
    The comment has been removed

  • Anonymous
    December 03, 2008
    @Marc Just for an update. By default in the wizard the checkbox is off of non-english locales. There was a debate internally about making it off and disabling it too in these situations. But we decided some people may still want to use this anyway. Regards Alex

  • Anonymous
    December 03, 2008
    I agree that a more general mechanism is need for name transformation than just pluralization. When dealing with large databases, the amount of effort it takes to transform names from db conventions to code conventions can be overwhelming. And there is no reason why the majority of that effort can't be handled automatically, if a facility is available to do it.

  • Anonymous
    December 07, 2008
    @AlexJ goog decision not disabling it but turning it off only. I work for a German company and we name our tables English so the pluralization feature will still be useful for us. Though I must confess that we use the English version of Visual Studio anyway because of the poor German translation (which is, however, still a lot better than in Windows Vista) ;)

  • Anonymous
    March 04, 2009
    There are two pain points for me in EF in this regard, not related to pluralization/singularization. Name generation/inference in EF is not on par with other features. I can't manually renamed 45 tables and a couple of hundred properties because EF copied names as it is. https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=374920 https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=374922 First one has been closed as by design, second one is still active. And honestly, its the second one which needs much more attention.

  • Anonymous
    June 06, 2009
    I think it would be more convenient if we could set custom pluraluzation-serivice at designer or at app.config.