Chciałbym użyć Entity-Framework 5.0 jako programu odwzorowującego O/R z bazą danych PostgreSql. Czytałem już wiele porad, ale nadal utknąłem. Może nie rozumiem całej idei EF.Entity-Framework 5.0 z PostgreSQL
Czego chcę:
- Chcę napisać kod przez własną rękę. Następnie umieść kilka atrybutów we właściwościach i klasach, aby powiedzieć EF, jak odwzorować obiekty (tak jak zrobiłbym to przy pomocy NHibernate).
- Nie chcę generować bazy danych z mojego modelu - chcę tylko użyć istniejącej.
Przykład Model:
[Table("device")]
public class Device
{
[Key]
public int Id { get; set; }
[StringLength(255)]
public string Identifier { get; set; }
}
[Table("customer")]
public class Customer
{
public Customer()
{
this.Devices = new List<Device>();
}
[Key]
public int Id { get; set; }
[StringLength(255)]
public string Name { get; set; }
// attribute required?
public List<Device> Devices { get; set; }
}
Co zrobiłem:
- Napisanie kodu powyżej
- Utworzono klasę DatabaseContext
- Dodany DbProviderFactories i connectionStrings w th e app.config
- Generated SSDL, MSL, CSDL plików za pomocą narzędzia EdmGen.exe i kopiowane je w projekcie (te pliki w folderze bin są również)
DatabaseContext:
public class DatabaseContext : DbContext
{
static DatabaseContext()
{
Database.SetInitializer<DatabaseContext>(null);
}
public DatabaseContext()
: base("PostgreSQL")
{
}
public DbSet<Customer> Customers { get; set; }
public DbSet<Device> Devices { get; set; }
}
app.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.data>
<DbProviderFactories>
<remove invariant="Npgsql" />
<add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql Server" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
</DbProviderFactories>
</system.data>
<connectionStrings>
<add name="PostGreSQL"
providerName="System.Data.EntityClient"
connectionString="metadata=.;provider=Npgsql;provider connection string="Server=asdf;Port=5432;User Id=asdf;Password=asdf;Database=asdf;enlist=true"" />
</connectionStrings>
</configuration>
Test:
using (DatabaseContext context = new DatabaseContext())
{
if (context.Database.Exists())
{
Console.WriteLine("yep");
}
else
{
Console.WriteLine("nope");
}
foreach (Customer c in context.Customers)
{
Console.WriteLine("Name={0}", c.Name);
}
}
Console.ReadLine();
Wyjście & Błąd:
"yep" .. co oznacza bazy istnieją. Ale gdy dostęp do właściwości context.Customers pojawia się następujący wyjątek:
The entity type Customer is not part of the model for the current context.
StackTrace:
at System.Data.Entity.Internal.InternalContext.UpdateEntitySetMappingsForType(Type entityType)
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator()
at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator()
at EF5.Program.Main(String[] args) in c:\Users\tba\Documents\Visual Studio 2012\Projects\EF5\EF5\Program.cs:line 26
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
Co ja nie rozumiem:
- Jakie są ssdl, msl, csdl pliki dobre dla, jeśli DataAnnoations są dostępne?
- Dlaczego klasa Klient nie jest częścią modelu dla bieżącego kontekstu?
Podczas korzystania z narzędzia EdmGen.exe generuje on również plik ObjectLayer.cs, który zawiera klasy ObjectContext i entity.Problem polega na tym, że klasy encji pochodzą z EntityObject. Jeśli chcę używać klas jednostek jako klas biznesowych, jest to poważny problem, ponieważ klasy nie mogą pochodzić z żadnych innych klas.
Ponadto nie rozumiem, dlaczego generuje ObjectContext. Każde znalezione HowTo używa klasy DbContext.
Podmiot klasa klienta wygenerowany przez narzędzie EdmGen:
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmEntityTypeAttribute(NamespaceName="EF5", Name="Customer")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Customer : EntityObject
Jestem mylić :-)
Edit:
- Nie używam tych ObjectLayer.cs plik! I nie chcę tego również używać ze względu na problemy z dziedziczeniem, o których pisałem powyżej. Częściowa klasa klienta jest tylko przykładem do pokazania, co generuje narzędzie EdmGen.
Kiedy usunąć CSDL, MSL i plików SSDL pojawia się następujący błąd:
At least one SSDL artifact is required for creating StoreItemCollection.
Kiedy usunąć słowa kluczowego metadanych z właściwości ConnectionString w app.config pojawia się następujący błąd:
Some required information is missing from the connection string. The 'metadata' keyword is always required.
Rozwiązanie:
W końcu zorientowałem się, jak to działa. Metoda connectionString w pliku app.config jest niepoprawna. Prawidłowe połączenie: Ciąg znaków:
Usunąłem metadane, dostawcę i właściwość łańcucha połączenia dostawcy z connectionString. Podobnie jak w przypadku Brice, pliki metadanych nie są konieczne, dlatego właśnie je usunąłem.
Również atrybut tabeli dla urządzenia i klasy klienta musi określać schemat . W ten sposób:
[Table("customer", Schema="public")]
public class Customer
Wygląda na to, że próbujesz wymieszać przepływy pracy od pierwszego modelu do pierwszego kodu. Sprawdź niektóre z filmów Getting Started na stronie [http://msdn.com/data/ef](http://msdn.microsoft.com/en-us/data/ee712907), aby dowiedzieć się więcej o korzystaniu z EF. – bricelam
Prosty przykład byłby świetny. Projekt korzystający z EF5 z bazą danych PostgreSql. Bez żadnego projektanta, po prostu kod (przypisany kod). – bakunin
Zrobione: [Entity Framework na PostgreSQL] (http://brice-lambson.blogspot.com/2012/10/entity-framework-on-postgresql.html) – bricelam