Der SQL Anywhere .NET-Datenprovider unterstützt Entity Framework 4.2, ein separates Paket von Microsoft. Um Entity Framework 4.2 zu verwenden, müssen Sie es mit dem Microsoft NuGet Package Manager hinzufügen.
Eine der neuen Funktionen von Entity Framework ist Code First. Sie ermöglicht einen anderen Entwicklungs-Workflow: Definition von Datenmodellobjekten durch Schreiben von C#- oder VB.NET-Klassen, die Datenbankobjekten zugeordnet werden, ohne einen Designer öffnen oder eine XML-Zuordnungsdatei definieren zu müssen. Optional kann eine zusätzliche Konfiguration mit Daten-Annotations oder der Fluent API durchgeführt werden. Modelle können verwendet werden, um ein Datenbankschema zu generieren oder einer vorhandenen Datenbank zuzuordnen.
Dies ist ein Beispiel, bei dem neue Datenbankobjekte unter Zuhilfenahme des Modells erstellt werden:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; using iAnywhere.Data.SQLAnywhere; namespace CodeFirstExample { [Table( "EdmCategories", Schema = "DBA" )] public class Category { public string CategoryID { get; set; } [MaxLength( 64 )] public string Name { get; set; } public virtual ICollection<Product> Products { get; set; } } [Table( "EdmProducts", Schema = "DBA" )] public class Product { public int ProductId { get; set; } [MaxLength( 64 )] public string Name { get; set; } public string CategoryID { get; set; } public virtual Category Category { get; set; } } [Table( "EdmSuppliers", Schema = "DBA" )] public class Supplier { [Key] public string SupplierCode { get; set; } [MaxLength( 64 )] public string Name { get; set; } } public class Context : DbContext { public Context() : base() { } public Context( string connStr ) : base( connStr ) { } public DbSet<Category> Categories { get; set; } public DbSet<Product> Products { get; set; } public DbSet<Supplier> Suppliers { get; set; } protected override void OnModelCreating( DbModelBuilder modelBuilder ) { modelBuilder.Entity<Supplier>().Property( s => s.Name ).IsRequired(); } } class Program { static void Main( string[] args ) { Database.DefaultConnectionFactory = new SAConnectionFactory(); Database.SetInitializer<Context>( new DropCreateDatabaseAlways<Context>() ); using ( var db = new Context( "DSN=SQL Anywhere 12 Demo" ) ) { var query = db.Products.ToList(); } } } } |
Um dieses Beispiel zu erstellen und auszuführen, müssen die folgenden Assembly-Referenzen hinzugefügt werden:
EntityFramework iAnywhere.Data.SQLAnywhere.v4.0 System.ComponentModel.DataAnnotations System.Data.Entity |
Dies ist ein anderes Beispiel mit Zuordnung zu einer vorhandenen Datenbank:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; using iAnywhere.Data.SQLAnywhere; namespace CodeFirstExample { [Table( "Customers", Schema = "GROUPO" )] public class Customer { [Key()] public int ID { get; set; } public string SurName { get; set; } public string GivenName { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string Country { get; set; } public string PostalCode { get; set; } public string Phone { get; set; } public string CompanyName { get; set; } public virtual ICollection<Contact> Contacts { get; set; } } [Table( "Contacts", Schema = "GROUPO" )] public class Contact { [Key()] public int ID { get; set; } public string SurName { get; set; } public string GivenName { get; set; } public string Title { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string Country { get; set; } public string PostalCode { get; set; } public string Phone { get; set; } public string Fax { get; set; } [ForeignKey( "Customer" )] public int CustomerID { get; set; } public virtual Customer Customer { get; set; } } public class Context : DbContext { public Context() : base() { } public Context( string connStr ) : base( connStr ) { } public DbSet<Contact> Contacts { get; set; } public DbSet<Customer> Customers { get; set; } } class Program { static void Main( string[] args ) { Database.DefaultConnectionFactory = new SAConnectionFactory(); Database.SetInitializer<Context>( null ); using ( var db = new Context( "DSN=SQL Anywhere 12 Demo" ) ) { foreach ( var customer in db.Customers.ToList() ) { Console.WriteLine( "Customer - " + string.Format( "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}", customer.ID, customer.SurName, customer.GivenName, customer.Street, customer.City, customer.State, customer.Country, customer.PostalCode, customer.Phone, customer.CompanyName ) ); foreach ( var contact in customer.Contacts ) { Console.WriteLine( " Contact - " + string.Format( "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}", contact.ID, contact.SurName, contact.GivenName, contact.Title, contact.Street, contact.City, contact.State, contact.Country, contact.PostalCode, contact.Phone, contact.Fax ) ); } } } } } } |
Es gibt einige Detailunterschiede bei der Implementierung zwischen dem Microsoft SQL Server SqlClient Provider und dem SQL Anywhere .NET Provider, die Sie beachten müssen.
Eine neue Klasse SAConnectionFactory (implementiert IDbConnectionFactory) ist enthalten. Sie legen die Database.DefaultConnectionFactory mit einer Instanz von SAConnectionFactory fest, bevor Sie ein Datenmodell erstellen. Dies wird nachstehend gezeigt:
Database.DefaultConnectionFactory = new SAConnectionFactory(); |
Das wichtigsten Prinzip von Entity Framework Code First ist die Programmierung nach Konventionen. Das Entity Framework leitet das Datenmodell durch Programmierungskonventionen ab. Entity Framework führt vieles auch implizit durch. In einigen Fällen realisiert der Entwickler vielleicht nicht alle diese Entity Framework-Konventionen. Aber einige Programmkonventionen sind für SQL Anywhere nicht sinnvoll. Es gibt einen großen Unterschied zwischen SQL Server und SQL Anywhere. Jede SQL Server-Instanz verwaltet mehrere Datenbanken. Jede SQL Anywhere-Datenbank ist hingegen eine einzelne Datei.
Wenn der Benutzer einen benutzerdefinierten DbContext mit einem Konstruktor ohne Parameter erstellt, verbindet sich SqlClient mit SQL Server Express auf dem lokalen Rechner mit der integrierten Sicherheit. Der SQL Anywhere-Provider stellt eine Verbindung mit dem Standardserver mit integriertem Login her, wenn der Benutzer bereits eine Login-Zuordnung erstellt hat.
SqlClient entfernt die vorhandene Datenbank und erstellt eine neue Datenbank, wenn EF DbDeleteDatabase oder DbCreateDatabase aufruft (nur SQL Server Express). Der SQL Anywhere-Provider wird nie eine Datenbank entfernen oder erstellen. Er erstellt oder entfernt die Datenbankobjekte (Tabellen, Beziehungen, Integritätsregeln beispielsweise). Der Benutzer muss die Datenbank zunächst erstellen.
Die IDbConnectionFactory.CreateConnection Methode behandelt den Zeichenfolgenparameter "nameOrConnectionString" als Datenbanknamen (anfänglicher Katalog für SQL Server) oder als Verbindungszeichenfolge. Wenn der Benutzer die Verbindungszeichenfolge für DbContext nicht bereitstellt, verbindet sich SqlClient automatisch mit dem SQL Express Server auf dem lokalen Rechner mit dem Namespace der benutzerdefinierten DbContext-Klasse als ursprünglichen Katalog. Für SQL Anywhere kann dieser Parameter nur eine Verbindungszeichenfolge enthalten. Ein Datenbankname wird ignoriert und integriertes Login wird anstelle dessen verwendet.
Die SQL Server SqlClient-API ordnet eine Spalte mit dem Daten-Annotationsattribut TimeStamp dem SQL Server-Datentyp timestamp/rowversion zu. Bei Entwicklern wird SQL Server timestamp/rowversion oft falsch verstanden. Der SQL Server timestamp/rowversion-Datentyp unterscheidet sich von SQL Anywhere und den meisten anderen Datenbankherstellern:
SQL Server timestamp/rowversion ist binary(8). Er unterstützt keine kombinierten Datums- und Uhrzeitwerte. SQL Anywhere unterstützt einen Datentyp mit dem Namen timestamp, der dem SQL Server datetime-Datentyp entspricht.
SQL Server timestamp/rowversion-Werte sind garantiert eindeutig. SQL Anywhere-Zeitstempelwerte sind nicht eindeutig.
Ein SQL Server timestamp/rowversion-Wert ändert sich jedes Mal, wenn die Zeile aktualisiert wird.
Das TimeStamp Daten-Annotation-Attribut wird vom SQL Anywhere-Provider nicht unterstützt.
Standardmäßig setzt Entity Framework 4.1 den Schema- oder Eigentümernamen auf dbo, also das standardmäßige Schema von SQL Server. Allerdings ist dbo für SQL Anywhere nicht geeignet. Für SQL Anywhere müssen Sie den Schemanamen (GROUPO beispielsweise) mit dem Tabellennamen mit über Daten-Annotations oder die Fluent API angeben. Hier ist ein Beispiel:
namespace CodeFirstTest { public class Customer { [Key()] public int ID { get; set; } public string SurName { get; set; } public string GivenName { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string Country { get; set; } public string PostalCode { get; set; } public string Phone { get; set; } public string CompanyName { get; set; } public virtual ICollection<Contact> Contacts { get; set; } } public class Contact { [Key()] public int ID { get; set; } public string SurName { get; set; } public string GivenName { get; set; } public string Title { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string Country { get; set; } public string PostalCode { get; set; } public string Phone { get; set; } public string Fax { get; set; } [ForeignKey( "Customer" )] public int CustomerID { get; set; } public virtual Customer Customer { get; set; } } [Table( "Departments", Schema = "GROUPO" )] public class Department { [Key()] public int DepartmentID { get; set; } public string DepartmentName { get; set; } public int DepartmentHeadID { get; set; } } public class Context : DbContext { public Context() : base() { } public Context( string connStr ) : base( connStr ) { } public DbSet<Contact> Contacts { get; set; } public DbSet<Customer> Customers { get; set; } public DbSet<Department> Departments { get; set; } protected override void OnModelCreating( DbModelBuilder modelBuilder ) { modelBuilder.Entity<Contact>().ToTable( "Contacts", "GROUPO" ); modelBuilder.Entity<Customer>().ToTable( "Customers", "GROUPO" ); } } } |
![]() |
Kommentieren Sie diese Seite in DocCommentXchange.
|
Copyright © 2012, iAnywhere Solutions, Inc. - SQL Anywhere 12.0.1 |