Zur Zeit wird gefiltert nach: murphy
Filter zurücksetzen

Entity Framework 4.3 - Building Blocks oder wie steuer ich die Datenbankversion

Gelegentlich kommt es vor, dass die Datenbankversionen pro Umgebung unterschiedlich sein können. Bei meinen ersten versuchen ist mir das mit den SQL-Server Versionen 2005 und 2008 so ergangen.

Sofort ersichtlich wurde das, wenn die folgende Fehlermeldung im Log zu sehen war:

System.ArgumentException: The version of SQL Server in use does not support datatype 'datetime2'

Um dies in den Griff zu bekommen gibt es das Attribut "ProviderManifestToken" in der EDMX-Datei. Mit dem ERM-Ansatz lassen sich, neben unterschiedlen Datenbanken, auch unterschiedliche Versionen einer Datenbank verwalten und mappen. Ein sehr interessanter Ansatz bei der Realisierung von Standardsoftware.

Nun stellt sich die Frage, wie mache ich das in Code First mit Schema Migrations?

Der Schlüssel liegt dabei in der Klasse DbModelBuilder. Beim erstellen kann damit die Datenbankversion definiert werden.


// default
var model = builder.Build(connection);

// with version
var model = builder.Build(new DbProviderInfo("System.Data.SqlClient", "2005"));

Gerade mit der nächsten Version von SQL Server 2012 wird es sicherlich ähnliche Probleme geben können, wenn die Systemumgebungen trotz ITIL nicht ganz so synchron sind. Bei der erstmaligen Erstellung des Models wird das sicherlich nicht von Bedeutung sein, wohl aber bei Schema Migrations.

Im Blogbeitrag von Arthur Vickers finden sich noch andere interessante Punkte die interessant sind, so auch die Aussage das Pluggable Conventions für den Durchschnittsentwickler frühstens mit EF6 nutzbar werden, wenn überhaupt.

Weitere Informationen zum Thema:

Zurück

15.03.2012
22:54

Sharepoint Deployment API zwischen Version 2007 und 2010

Meine Migrationsstory geht weiter. Nachdem der Export vorlag, stand ich das erste Mal an, weil mich bei einem Testimport die Fehlermeldung:

The version of the package 12.0.10.0 is different from the current version this program supports, 14.0.0.0

begrüsste. Nach ein bisschen suchen fand ich einen Ansatz. Die Package Files, speziell die SystemData.xml muss angepasst werden, damit sich der Inhalt aus Sharepoint 2007 in Sharepoint 2010 importieren lässt.

In der XML-Datei muss dazu auf SchemaVersion-Ebene die Version, dass aktuelle Patchlevel (Build) und die Datenbankversion (DatabaseVersion) angegeben werden. Nachfolgendes XML zeigt einen Ausschnitt aus der SystemData.xml:


<?xml version="1.0" encoding="utf-8"?>
<SystemData xmlns="urn:deployment-systemdata-schema">
    <SchemaVersion Version="14.0.0.0" Build="14.0.6109.5002" DatabaseVersion="133739" SiteVersion="0" ObjectsProcessed="27" />
    <ManifestFiles>
        <ManifestFile Name="Manifest.xml" />
    </ManifestFiles>
    <SystemObjects>
        ...
    </SystemObjects>
    <RootWebOnlyLists />
</SystemData>

Müssten die Daten nicht noch bereinigt und transformiert werden, wäre ich bereits am Ende. Nun geht es daran, die XML-Dateien so aufzubereiten, damit die Daten in das Format der neuen Lösung des Zielsystems importiert werden können.

ETL geht auch einfacher, aber nicht unbedingt wenn Sharepoint im Spiel ist. ;-)

Weitere Informationen zum Thema:

Zurück

29.02.2012
22:03

Sharepoint 2010 Best Practices

Sharepoint gehört immer noch zu meinen Aufgabengebieten. Gute Anleitungen zu finden ist auch nicht einfach, gerade im Bezug was man tun oder lassen sollte.

Das Produktteam hat eine Übersicht mit Best Practices unter dem Link bereitgestellt.

Mal sehen, ob es brauchbar ist...

Weitere Informationen zum Thema:

Zurück

Entity Framework 4 - Der Designer stottert bei zusammengesetzten Schlüsseln (CompositeKey)

Heute wurde ich mit einem interessanten Problem im Entity Designer bei zusammengesetzten Schlüsseln konfrontiert. Das Modell wurde mit dem Assistenten angelegt. Dabei war die Einstellungen "Fremdschlüsselspalten in das Modell einbeziehen" aktiviert und es wurde die Standard-Code Generierungsvorlage verwendet.

Das Modell hatte in etwa folgenden Aufbau:

Abbildung 1
Abbildung 1 Teilmodell im Entity Framework mit Composite Key

Der erste Test, der sich mit dem Einfügen von Daten in die Datenbank befasste, scheiterte und lieferte folgendes Resultat:

Abbildung 2
Abbildung 2 Insert-Test schlägt fehl, bei Entitäten mit Composite Key

Die passende Fehlermeldung dazu lautet:

Die Personen.Test.CommentTest.Comment_Insert_Test-Testmethode hat eine Ausnahme ausgelöst: System.Data.UpdateException: EntitySet 'Comment' kann nicht aktualisiert werden, denn es hat eine DefiningQuery, und im <ModificationFunctionMapping>-Element ist kein <InsertFunction>-Element zur Unterstützung des aktuellen Vorgangs vorhanden.

Im ersten Moment beginnt das überlegen, DefiningQuery? Warum legt der Designer ein DefiningQuery für diese Tabelle an? In diesem Fall kann der Insert-Mechanismus gar nicht funktionieren, weil keine Prozeduren vorhanden sind. Ein Blick in das XML (Öffnen mit XML Text Editor) bestätigt auch die Fehlermeldung:


    <edmx:StorageModels>
      <Schema Namespace="Model.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
        <EntityContainer Name="ModelStoreContainer">
          <EntitySet Name="Comment" EntityType="Model.Store.Comment" store:Type="Tables" store:Schema="dbo" store:Name="Comment">
            <DefiningQuery>SELECT 
      [Comment].[PersonID] AS [PersonID], 
      [Comment].[CommentTypeID] AS [CommentTypeID], 
      [Comment].[Note] AS [CO_Note]
      FROM [dbo].[Comment] AS [Comment]</DefiningQuery>
          </EntitySet>

Prozeduren will ich für dieses Szenario auf keinen Fall generieren, also bleibt mir nichts anderes übrig, als das XML anzupassen. Dazu gehe ich folgendermassen vor:

  1. DefinigQuery-Tag mit Inhalt entfernen
  2. store:Name=“Comment“ entfernen
  3. store:Schema=“dbo“ ändern in Schema=“dbo“
  4. XML-Datei speichern

Ist das Ganze angepasst, bleibt folgendes XML übrig:

    
              <EntitySet Name="Comment" EntityType="Model.Store.Comment" store:Type="Tables" Schema="dbo" >
              </EntitySet>
    
    

    Zur Sicherheit wird das File im Designer geöffnet und validiert. Nach dieser Anpassung wird der Test erneut ausgeführt und der Einfüge-Test läuft nun fehlerfrei.

    Abbildung 3
    Abbildung 3 Test nach Anpassung der XML-Datei

    Daraus lässt sich schliessen, dass auch im Entity Framework 4 ein wenig Basiswissen zum Aufbau der XML-Datei nicht schaden kann. Den Nachteil dieser Variante will ich auch nicht vorenthalten. Mit jeder Modell-Anpassung müssen diese Schritte wiederholt werden.

    Dieses Problem kann bei der codezentrierten Anwendungsentwicklung mit dem DbContext sicherlich auch entstehen, da der DbContext das XML zur Laufzeit erstellt. Dann besteht nicht die einfache Möglichkeit, dass XML anzupassen. Wer mit anderen Datenbanken wie zum Beispiel MySQL im codezentrierten Ansatz gearbeitet hat, kennt sicherlich die Probleme jenseits des dbo-Schemas. ;-)

    Zurück

    24.07.2011
    15:03

    T4 und der Zugriff auf die App.config

    Zur Zeit sitze ich mal wieder tief in der T4-Materie. Dabei war mal wieder die zufällige Erstellung von AppDomains eine kleine Bremse. Das ist eine ganz spezielle Eigenart, die zum Beispiel auch dafür sorgt, dass auf die App.config der Solution nicht direkt zugegriffen werden kann.

    Im Blog von Sky Sander fand ich einen schönen Workaround, damit der Zugriff doch wieder ermöglicht werden kann.

    Bei Gelegenheit muss ich mal überprüfen, ob sich die zufällige Erstellung der T4-AppDomains irgendwie in den Griff bekommen lässt.

    Nachfolgend der Workaround, der bei mir in Form einer Include-Datei mit Namen ConfigurationAccessor.CS.ttinclude verwendet wird:

    
    <#@ assembly name="System.Configuration" #>
    <#@ assembly name="EnvDTE" #>
    <#@ import namespace="System.Configuration" #>
    <#@ import namespace="System.Text.RegularExpressions" #>
    <#+
    /// <summary>
    /// Provides strongly typed access to the hosting EnvDTE.Project and app.config/web.config 
    /// configuration file, if present.
    /// 
    /// Typical usage from T4 template:
    /// <code>ConfigurationAccessor config = new ConfigurationAccessor((IServiceProvider)this.Host);</code>
    /// </summary>
    /// <author>Sky Sanders [sky.sanders@gmail.com, http://skysanders.net/subtext]</author>
    /// <date>01-23-10</date>
    /// <copyright>The contents of this file are a Public Domain Dedication.</copyright>
    public class ConfigurationAccessor
    {
       /// <summary>
       /// Typical usage from T4 template:
       /// <code>ConfigurationAccessor config = new ConfigurationAccessor((IServiceProvider)this.Host);</code>
       /// </summary>
       public ConfigurationAccessor(IServiceProvider host)
       {
          // Get the instance of Visual Studio that is hosting the calling file
          EnvDTE.DTE env = (EnvDTE.DTE)host.GetService(typeof(EnvDTE.DTE));
          // Gets an array of currently selected projects. Since you are either in this file saving it or
          // right-clicking the item in solution explorer to invoke the context menu it stands to reason
          // that there is 1 ActiveSolutionProject and that it is the parent of this file....
          _project = (EnvDTE.Project)((Array)env.ActiveSolutionProjects).GetValue(0);
          string configurationFilename=null;  
          // examine each project item's filename looking for app.config or web.config
          foreach (EnvDTE.ProjectItem item in _project.ProjectItems)
          {
                if (Regex.IsMatch(item.Name,"(app|web).config",RegexOptions.IgnoreCase))
                {
                    // TODO: try this with linked files. is the filename pointing to the source?
                    configurationFilename=item.get_FileNames(0);
                    break;
                }
          }
    
          if(!string.IsNullOrEmpty(configurationFilename))
          {
               // found it, map it and expose salient members as properties
               ExeConfigurationFileMap configFile = null;
               configFile = new ExeConfigurationFileMap();
               configFile.ExeConfigFilename=configurationFilename;
    
               _configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
          }
      }
    
      private EnvDTE.Project _project;
      private System.Configuration.Configuration _configuration;
    
      /// <summary>
      /// Provides access to the host project.
      /// </summary>
      /// <remarks>see http://msdn.microsoft.com/en-us/library/envdte.project.aspx</remarks>
      public EnvDTE.Project Project
      {
          get { return _project; }
      }
    
      /// <summary>
      /// Convenience getter for Project.Properties.
      /// Examples:
      /// <code>string thisAssemblyName = config.Properties.Item("AssemblyName").Value.ToString();</code>
    
      /// <code>string thisAssemblyName = config.Properties.Item("AssemblyName").Value.ToString();</code>
      /// </summary>
      /// <remarks>see http://msdn.microsoft.com/en-us/library/envdte.project_properties.aspx</remarks>
      public EnvDTE.Properties Properties 
      {
           get { return _project.Properties;}
      }
    
      /// <summary>
      /// Provides access to the application/web configuration file.
      /// </summary>
      /// <remarks>see http://msdn.microsoft.com/en-us/library/system.configuration.configuration.aspx</remarks>
      public System.Configuration.Configuration Configuration
      {
           get { return _configuration; }
      }   
    
      /// <summary>
      /// Provides access to the appSettings section of the configuration file.
      /// Behavior differs from typical AppSettings usage in that the indexed
      /// item's .Value must be explicitly addressed.
      /// <code>string setting = config.AppSettings["MyAppSetting"].Value;</code>
    
      /// </summary>
      /// <remarks>see http://msdn.microsoft.com/en-us/library/system.configuration.configuration.appsettings.aspx</remarks>
      public  KeyValueConfigurationCollection AppSettings
      {
           get { return _configuration.AppSettings.Settings;}
      }
    
      /// <summary>
      /// Provides access to the connectionStrings section of the configuration file.
      /// Behavior is as expected; items are accessed by string key or integer index.
      /// <code>string northwindProvider = config.ConnectionStrings["northwind"].ProviderName;</code>
      /// </summary>
      /// <remarks>see http://msdn.microsoft.com/en-us/library/system.configuration.configuration.connectionstrings.aspx</remarks>
      public  ConnectionStringSettingsCollection ConnectionStrings
      {
            get { return _configuration.ConnectionStrings.ConnectionStrings;}
      }
    }#>
    
    

    Zurück

    Translate this page

    Kategorien

    • [-].NET Development (215)
    • [-]Datenbank (26)
    • HTML (1)
    • Konfiguration (12)
    • Mind Map (10)
    • Off-topic (9)
    • Open Source (3)
    • Qualität (7)
    • Sharepoint (6)
    • Sicherheit (2)

    Archiv

    Social Bookmarking

    Bookmark bei: Mr. Wong Bookmark bei: Webnews Bookmark bei: Icio Bookmark bei: Oneview Bookmark bei: Linkarena Bookmark bei: Favoriten Bookmark bei: Seekxl Bookmark bei: Favit Bookmark bei: Social Bookmarking Tool Bookmark bei: Power Oldie Bookmark bei: Bookmarks.cc Bookmark bei: Newskick Bookmark bei: Newsider Bookmark bei: Linksilo Bookmark bei: Readster Bookmark bei: Folkd Bookmark bei: Yigg Bookmark bei: Digg Bookmark bei: Del.icio.us Bookmark bei: Reddit Bookmark bei: Simpy Bookmark bei: StumbleUpon Bookmark bei: Slashdot Bookmark bei: Netscape Bookmark bei: Furl Bookmark bei: Yahoo Bookmark bei: Spurl Bookmark bei: Google Bookmark bei: Blinklist Bookmark bei: Blogmarks Bookmark bei: Diigo Bookmark bei: Technorati Bookmark bei: Newsvine Bookmark bei: Blinkbits Bookmark bei: Ma.Gnolia Bookmark bei: Smarking Bookmark bei: Netvouz Information