Neste post, mostro que é possível utilizar EF com o banco de dados Oracle. Existem diversos providers de Oracle para o EF, um bom exemplo é o da DevArt (dotConnect), porém é uma solução paga. A própria Oracle está desenvolvendo um provedor com suporte ao Entity Framework, porém até o momento deste POST ainda se encontra na versão Beta 3, porém em breve teremos a versão de produção, aí então é só atualizar.
Pré-requisitos:
* ORACLE 10G express edition previamente instalado
http://www.oracle.com/technetwork/database/express-edition/database10gxe-459378.html
* ODAC1120250Beta_EntityFramework_32bit_xcopy
http://www.oracle.com/technetwork/developer-tools/visual-studio/downloads/index.html
* EntityFramework Code First 4.1
http://www.microsoft.com/download/en/details.aspx?id=26825
Mãos à massa!
Crie um novo usuário no Oracle, para este post criei um usuário chamado REPOSITORIO. O banco de dados para este exemplo consite em uma tabela de PESSOAS, que possui zero ou mais telefones, relacionada com uma tabela de TELEONES A estrutura do banco de dados ficou assim:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE TABLE "PESSOAS" | |
( "ID" NUMBER, | |
"NOME" VARCHAR2(50), | |
CONSTRAINT "PESSOAS_PK" PRIMARY KEY ("ID") ENABLE | |
) | |
/ | |
CREATE TABLE "TELEFONES" | |
( "ID" NUMBER NOT NULL ENABLE, | |
"PESSOA_ID" NUMBER NOT NULL ENABLE, | |
"NUMERO" VARCHAR2(10) NOT NULL ENABLE, | |
CONSTRAINT "TELEFONES_PK" PRIMARY KEY ("ID") ENABLE, | |
CONSTRAINT "TELEFONES_FK" FOREIGN KEY ("PESSOA_ID") | |
REFERENCES "PESSOAS" ("ID") ENABLE | |
) | |
/ | |
Rem Nenhum function encontrado para gerar a DDL. | |
CREATE UNIQUE INDEX "PESSOAS_PK" ON "PESSOAS" ("ID") | |
/ | |
CREATE UNIQUE INDEX "TELEFONES_PK" ON "TELEFONES" ("ID") | |
/ | |
Rem Nenhum procedure encontrado para gerar a DDL. | |
CREATE SEQUENCE "PESSOAS_SEQ" MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 21 CACHE 20 NOORDER NOCYCLE | |
/ | |
CREATE SEQUENCE "TELEFONES_SEQ" MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 21 CACHE 20 NOORDER NOCYCLE | |
/ | |
CREATE OR REPLACE TRIGGER "BI_PESSOAS" | |
before insert on "PESSOAS" | |
for each row | |
begin | |
select "PESSOAS_SEQ".nextval into :NEW.ID from dual; | |
end; | |
/ | |
ALTER TRIGGER "BI_PESSOAS" ENABLE | |
/ | |
CREATE OR REPLACE TRIGGER "BI_TELEFONES" | |
before insert on "TELEFONES" | |
for each row | |
begin | |
select "TELEFONES_SEQ".nextval into :NEW.ID from dual; | |
end; | |
/ | |
ALTER TRIGGER "BI_TELEFONES" ENABLE | |
/ |
Crie uma nova aplicação Console e adicione as seguintes referencias:
* EntityFramework.dll
* Oracle.DataAccess.dll (na pasta de instalação do Client do Oracle)
Veja o código completo da aplicação Console (coloquei todas as classes no mesmo arquivo Program.cs para este post, obviamente costumo separar um arquivo para cada classe nos meus projetos) :
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//POST: http://silverlightrush.blogspot.com/2011/11/receita-de-bolo-para-ef-code-first-e.html | |
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel.DataAnnotations; | |
using System.Data.Common; | |
using System.Data.Entity; | |
using System.Data.Entity.Infrastructure; | |
using System.Linq; | |
using Oracle.DataAccess.Client; | |
namespace ConsoleApplication3 | |
{ | |
/// <summary> | |
/// Classe que retorna a conexão com o banco de dados | |
/// </summary> | |
public class OracleConnectionFactory : IDbConnectionFactory | |
{ | |
public DbConnection CreateConnection(string nameOrConnectionString) | |
{ | |
return new OracleConnection(nameOrConnectionString); | |
} | |
} | |
/// <summary> | |
/// Classe mapeada para a tabela de Pessoas | |
/// </summary> | |
[Table("PESSOAS", Schema = "REPOSITORIO")] | |
public class Pessoa | |
{ | |
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), Column("ID")] | |
public decimal Id { get; set; } | |
[Column("NOME"), StringLength(50)] | |
public string Nome { get; set; } | |
public virtual ICollection<Telefone> Telefones { get; set; } | |
public Pessoa() | |
{ | |
Telefones = new HashSet<Telefone>(); | |
} | |
} | |
/// <summary> | |
/// Classe mapeada para a tabela de Telefones | |
/// </summary> | |
[Table("TELEFONES", Schema = "REPOSITORIO")] | |
public class Telefone | |
{ | |
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), Column("ID")] | |
public decimal Id { get; set; } | |
[Required, Column("PESSOA_ID")] | |
public decimal? PessoaId { get; set; } | |
[ForeignKey("PessoaId")] | |
public virtual Pessoa Pessoa { get; set; } | |
[StringLength(10), Required, Column("NUMERO")] | |
public string Numero { get; set; } | |
} | |
/// <summary> | |
/// Classe que representa o Contexto a ser utilizado para acesso ao banco | |
/// </summary> | |
public class MyDbContext : DbContext | |
{ | |
private const string ConnectionString | |
= "DATA SOURCE=SERVER_ORACLE; User Id=REPOSITORIO; PASSWORD=repositorio; Persist Security Info=true"; | |
static MyDbContext() | |
{ | |
Database.DefaultConnectionFactory = new OracleConnectionFactory(); | |
} | |
public MyDbContext() | |
: base(ConnectionString) | |
{ | |
} | |
public DbSet<Pessoa> Pessoas { get; set; } | |
public DbSet<Telefone> Telefones { get; set; } | |
} | |
/// <summary> | |
/// Código para a aplicação Console | |
/// </summary> | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
using (var db = new MyDbContext()) | |
{ | |
//adicionar uma pessoa | |
var pessoa = new Pessoa { Nome = "Jone Polvora" }; | |
db.Pessoas.Add(pessoa); | |
db.SaveChanges(); | |
//adicionar um telefone para a pessoa | |
var telefone = new Telefone { Numero = "6712345678", Pessoa = pessoa }; | |
db.Telefones.Add(telefone); | |
db.SaveChanges(); | |
//imprime a lista de pessoas | |
foreach (var p in db.Pessoas.ToList()) | |
{ | |
Console.WriteLine(p.Nome); | |
//imprime os telefones da pessoa atual | |
foreach (var t in p.Telefones) | |
{ | |
Console.WriteLine(t.Numero); | |
} | |
} | |
//alterar a pessoa | |
pessoa.Nome = "Outro nome"; | |
db.SaveChanges(); | |
//remover o telefone da pessoa | |
db.Telefones.Remove(telefone); | |
db.SaveChanges(); | |
//remover a pessoa | |
db.Pessoas.Remove(pessoa); | |
db.SaveChanges(); | |
Console.WriteLine("Pressione Delete para remover todos os registros"); | |
var key = Console.ReadKey(); | |
if (key.Key == ConsoleKey.Delete) | |
{ | |
db.Telefones.OrderBy(t => t.Id).ToList().ForEach(t => db.Telefones.Remove(t)); | |
db.Pessoas.OrderBy(p => p.Id).ToList().ForEach(p => db.Pessoas.Remove(p)); | |
db.SaveChanges(); | |
} | |
} | |
} | |
} | |
} |