Sie sind hier: Weblog

Deutsche Pluralisierung in Entity Framework Code First

Foto ,
30.11.2013 23:49:00

Seit Version 6 kann man die Pluralisierung, die Entity Framework durchführt, anpassen. Auf diese Weise lassen sich Tabellennamen, die im Plural gehalten ist, aus den Klassennamen, die im Singular vorliegen, beim Einsatz von Code First ableiten. Dazu ist das Interface IPluralizationService zu implementieren. Dieses Interface gibt zwei Methoden vor: Pluralize und Singularize. Sie nehmen jeweils einen String entgegen und haben die Aufgabe, den entsprechenden Plural bzw. den entsprechenden Singular zu retournieren. Registriert wird ein auf diese Weise geschaffener Service über eine Instanz von DbConfiguration, die - sofern es im Projekt nur eine gibt - automatisch von Entity Framework genutzt wird.

Nachfolgend platziere ich eine Implementierung von IPluralizationService, welche den deutschen Plural sowie den deutschen Singular unter Verwendung der Daten von de.wiktionary.org nutzt. Da mir kein Service bekannt ist, der den Zugriff auf die Ressourcen dieser Seite erlaubt, parse ich an dieser Stelle retournierte HTML. Dass das ein Hack ist, liegt auf der Hand. Auf der anderen Seite kommt man auf diese Weise kostenlos an die benötigten Informationen.

public class CustomPluralizationService: IPluralizationService
{

    public string FetchSingular(string word)
    {
        // Damn hack - didnt find a good web-service for this, so I have to parse HTML
        // If you know one, let me know

        string prefix;

        word = GetLastWordOfCompositeWord(word, out prefix);

        var url = "http://de.wiktionary.org/wiki/" + HttpUtility.UrlEncode(word);
        HttpClient client = new HttpClient();
        var result = client.GetAsync(url).Result; // No Async - sorry ;-|

        if (result.StatusCode != System.Net.HttpStatusCode.OK)
        {
            return null;
        }

        var content = result.Content.ReadAsStringAsync().Result; // No Async - sorry ;-|


        var idx = content.IndexOf("Nominativ Plural des Substantivs");
        if (idx == -1) return null;

        idx = content.IndexOf(">", idx+1);
        if (idx == -1) return null;

        idx = content.IndexOf(">", idx+1);
        if (idx == -1) return null;

        var idx2 = content.IndexOf("<", idx+1);
        if (idx2 == -1) return null;

        var singular = content.Substring(idx + 1, idx2 - idx - 1);

        singular = singular.Replace(" ", "");


            
        return prefix + singular;

    }

    public string FetchPlural(string word)
    {
        // Damn hack - didnt find a good web-service for this, so I have to parse HTML
        // If you know one, let me know

        string prefix;
            
        word = GetLastWordOfCompositeWord(word, out prefix);

        var url = "http://de.wiktionary.org/wiki/" + HttpUtility.UrlEncode(word);
        HttpClient client = new HttpClient();
        var result = client.GetAsync(url).Result; // No Async - sorry ;-|

        if (result.StatusCode != System.Net.HttpStatusCode.OK)
        {
            return null;
        }

        var content = result.Content.ReadAsStringAsync().Result; // No Async - sorry ;-|

        var idx = content.IndexOf("/wiki/Hilfe:Nominativ");
        if (idx == -1) return null;

        idx = content.IndexOf("<td", idx +1);
        if (idx == -1) return null;

        idx = content.IndexOf("<td", idx +1);
        if (idx == -1) return null;

        idx = content.IndexOf(">", idx +1);
        if (idx == -1) return null;

        var idx2 = content.IndexOf("</", idx+1);
        if (idx2 == -1) return null;

        var plural = content.Substring(idx + 1, idx2 - idx - 1);

        plural = plural.Replace(" ", "");

        var regex = new System.Text.RegularExpressions.Regex("<.*?>|der|die|das|");
        plural = regex.Replace(plural, "").Trim();

        return prefix + plural;

    }

    public string GetLastWordOfCompositeWord(string word, out string prefix)
    {
        StringBuilder sb = new StringBuilder(1024);

        for (int i = 0; i < word.Length; i++)
        {
            var c = word[i];

            if (char.IsUpper(c))
            {
                    
                sb.Clear();
            }
            sb.Append(c);
                
        }

        var result = sb.ToString();

        if (result == word)
        {
            prefix = "";
        }
        else
        {
            prefix = word.Substring(0, word.Length - result.Length);
        }

        return result;
    }

    public string Pluralize(string word)
    {
        var result = FetchPlural(word);
        if (result == null) return word;
        return result;
    }

    public string Singularize(string word)
    {
        var result = FetchSingular(word);
        if (result == null) return word;
        return result;
    }
}

 Der Vollständigkeit halber findet man nachfolgend die dazupassende DbConfiguration-Klasse. Ist diese vorhanden, sollte Entity Framework Code First sowie Migrations für Tabellennamen den deutschen Plural verwenden.
public class CustomDbConfiguration : DbConfiguration
{
    public CustomDbConfiguration()
    {

        SetPluralizationService(new CustomPluralizationService());
    }
}