Arquivo

Posts Tagged ‘nhibernate’

Unique Constraint – Entity Framework 6 – WTF

Iniciei um projeto em C# Windows Forms utilizando o Entity Framework 6 (última versão até o momento 05/01/2014).

Tenho um campo que armazena “e-mail”, e esse campo deve ser único na tabela.

Estou mapeando minhas classes utilizando FLUENT API.

e quando fui mapear a coluna E-MAIL fiquei assustado em descobrir que,

a versão 6 desse ORM  não tem esse recurso básico implementado na interface de mapeamento fluente.

Tem uma issue aberta no Codeplex para o tema:
https://entityframework.codeplex.com/workitem/57

Nesse momento reconsidero continuar o projeto em EF ou migrar urgentemente para NHIBERNATE que está anos-luz mais maduro.

Imagens no Oracle com NHibernate, Asp.net Mvc e C#

Cenário:
Um site de um concurso cultural, ao cadastrar uma promoção o usuário envia uma imagem que vai ser exibida com a promoção. Essa imagem é gravada no oracle com nhibernate, e é retornada sempre que a promoção é exibida ao usuário.

Exemplo resumido da classe Promoção:

public class Promocao
{
public virtual string Nome { get; set; }

public virtual string Desafio { get; set; }

public virtual string Regulamento { get; set; }

public virtual byte[] ImagemTopo { get; set; }
// Criamos a propriedade como um array de bytes -> byte[] que será persistido como binário.
}

Resumo da classe mapeada com Fluent NHibernate:

    public class PromocaoMap : ClassMap<Promocao>
    {
        public PromocaoMap()
        {
            .... omitido...            
            // Mapeei um campo para o regulamento da promoção e um campo para a imagem do topo
            Map(x => x.Regulamento).Length(1048576); // length de 1048576 bytes aproximadamente 1 mb -> será criado como NCLOB no oracle.
            Map(x => x.ImagemTopo).Length(5224880); // length 5224880 bytes aproximadamente 5 mb -> será criado como BLOB no oracle.
        }
    }

Gravando a imagem no banco

Código da Action que Recebe o Post do Form de Cadastro:

[HttpPost]
public ActionResult SavePromocao(Promocao promocaoGravar, HttpPostedFileBase ImagemTopoEnviar)
        {
            if (!ModelState.IsValid)
                return View("CadPromocao", promocaoGravar);

            using (var sessao = MvcApplication.ObterSessaoNh())
            {
                using (var transacao = sessao.BeginTransaction())
                {
                    try
                    {
                        var crud = new Dal.PromocaoDao(sessao);
                        if (promocaoGravar.Id <= 0)
                        {
                            crud.Incluir(promocaoGravar);
                        }
                        else
                        {
                            var objetoPersistido = crud.RetornaEntidade(promocaoGravar.Id);
                            objetoPersistido.Nome = promocaoGravar.Nome;

                            if (ImagemTopoEnviar != null)
                            {
                                // Converte stream do arquivo enviado para array de bytes[]
                                var memoryStream = new MemoryStream();
                                ImagemTopoEnviar.InputStream.CopyTo(memoryStream);

                                objetoPersistido.ImagemTopo = memoryStream.ToArray();
                            }

                            crud.Alterar(objetoPersistido);
                        }

                        transacao.Commit();
                    }
                    catch (Exception)
                    {
                        transacao.Rollback();
                    }
                }
            }

            return RedirectToAction("ListPromocoes");
        }

Dessa forma a imagem é persistida corretamente no Oracle.

Exibindo a imagem na view

Criar uma Action que busca a imagem no banco de dados e retorna via response

[HttpGet]
public ActionResult GetImagemPromocao(long idPromocao)
{
   byte[] imagemArray = null;

   using (var sessao = MvcApplication.ObterSessaoNh())
   {
	var crud = new Dal.PromocaoDao(sessao);
	imagemArray = crud.ObterImagem(idPromocao);
	if (imagemArray == null)
        {
		return null;
	}
	else
	{
		return new FileContentResult(imagemArray, "image/jpeg");
	} 
   }
} 

Código da View

// Minha View é TIPADA
<img src="@Url.Content("~/Admin/GetImagemPromocao?idPromocao = " + Model.Id)"/>

// O Helper Url.Content converte um Path Relativo para um Path Absoluto.

E assim a imagem é renderizada com sucesso na view.


Observações:

  1. Deve funcionar corretamente em outros SGBDS como MySql, PostgreSql e etc.
  2. Vale lembrar que o objeto byte[] armazena não somente imagems, mais qualquer outro tipo de arquivo, pois tudo é binário ok.
  3. Não inclui o tratamento de erros no exemplo.

Dúvidas deixe nos comentários que respondo.

Espero ter ajudado em seu projeto.


Referências:
Documentação do NHibernate – Tipos de Dados
Dica para converter Stream
no StackOverflow

Documentação Oficial de HTML Forms no W3C – World Wide Web Consortium.

Lançado NHibernate versão 3.3.0.GA

Lançada nova versão do NHibernate.

Versão final: 3.3.0

Vale a pena ao menos uma leitura dinâmica nas correções e melhorias.

Portal do NHibernate: http://nhforge.org/Default.aspx

Código Fonte: https://github.com/nhibernate/nhibernate-core

Build 3.3.0.GA
=============================

** Known BREAKING CHANGES from NH3.2.0.GA to NH3.3.0.GA

##### Possible Breaking Changes #####
* [NH-2214] – SQL Server 2005/2008: Exception is now thrown when paging a statement that requires distinct results, and is ordered by a column that is not included in the result set of the query
– Dialog.ExtractColumnOrAliasNames method signature and visibility changed – may affect custom dialects that use this method
* [NH-2950] – IAccessCallback.NextValue property renamed and changed to a method called IAccessCallback.GetNextValue()
* [NH-2953] – SequenceStyleGenerator now forces use of a table if a pooled optimizer is chosen and the dialect doesn’t support pooled sequences.
* [NH-2960] – Queries for an entity name will now not include instances of the same class mapped using a different entity name.
* [NH-2664] – IHqlExpressionVisitor has new property ISessionFactory SessionFactory { get; }
* [NH-3067] – The use of Substring() in Linq queries have been corrected so the zero-based index parameter in C# is converted to one-based index in SQL.
* [NH-2528] – Throw exception instead of silently truncate string and blob data
* [NH-3086] – The base dialect now defaults to ANSI syntax for substring. A custom dialect may need to adjust for this.

Leia mais…

PropertyAccessException com NHibernate

Ao acessar uma propriedade qualquer de minha classe mapeada, obtive o erro: PropertyAccessException.

Causa: Falta de atenção.

Bastou corrigir uma propriedade
List<Classe>

para:

IList<Classe>

Fica a dica.

Executando SQL ou HQL com NHibernate 3.2

Executar uma SQL (Structured Query Language) ou HQL (Hibernate Query Language) com NHibernate é muito simples.

1º Configure uma SessionFactory.
2º Gere uma sessão: ISession.
3º A partir da ISession vamos criar um objeto adequado para cada um dos casos.

EXECUTANDO SQL:

ISession sessaoCriada;
// Utilizando CreateSQLQuery para SQL
var sqlUpdate= sessaoCriada.CreateSQLQuery(
                    "update CLIENTE set DATACADASTRO = current_date where DATACADASTRO is null";
sqlUpdate.ExecuteUpdate();

EXECUTANDO HQL:

ISession sessaoCriada;
// Utilizando CreateQuery para HQL
var hqlUpdate= sessaoCriada.CreateQuery(
"update CLIENTE set DATACADASTRO = current_date where DATACADASTRO is null";
sqlUpdate.ExecuteUpdate();

Utilizando corretamente o objeto adequado você evitará que a exception: “could not execute native bulk manipulation query” seja levantada.

Até a próxima.

Configurando NHIBERNATE de 3 modos diferentes

Colocarei 3 porções de código mostrando como configurar uma Session Factory de NHIbernate utilizando: Fluent NHibernate, Arquivo XML, e via código.

Não se esqueça de adicionar as referências corretamente e substituir os valores-chave por seus próprios valores.

Leia mais…

NHibernate 3.2.0 GA – Mapping By Code

Transcrevo em português um exemplo do blog do Fabio Maulo: http://fabiomaulo.blogspot.com/2011/07/nhibernate-playing-with-mapping-by-code.html

Para responder algumas questões sobre Map By Code na nova versão do NHibernate será implementado o domínio abaixo:

// Classe base com atributo ID
public class Entity
 {
     public virtual int Id { get; set; }
 }
// Classe CLIENTE
public class Customer : Entity
 {
     public virtual string CommercialName { get; set; }
     public virtual string TaxId { get; set; }
     public virtual IEnumerable<Order> Orders { get; set; }
 }
// Classe PEDIDO
public class Order : Entity
 {
     public virtual Customer Customer { get; set; }
     public virtual DateTime EmissionDay { get; set; }
     public virtual IEnumerable<OrderItem> Items { get; set; }
 }
// Classe ITEM DO PEDIDO
public class OrderItem : Entity
 {
     public virtual Order Order { get; set; }
     public virtual string Product { get; set; }
     public virtual decimal Price { get; set; }
 }

Mapeando o Domínio:

// Mapeando classe base
public class EntityMapping<T> : ClassMapping<T> where T : Entity
 {
     public EntityMapping()
     {
         Id(x => x.Id);
     }
 }
// Herdando mapeamento da classe base
public class CustomerMapping : EntityMapping<Customer>
 {
     public CustomerMapping()
     {
         Property(x => x.CommercialName);
         NaturalId(map => map.Property(x => x.TaxId));
         Bag(x => x.Orders, map => map.Key(km => km.Column("CustomerId")));
     }
 }
public class OrderMapping : EntityMapping<Order>
 {
     public OrderMapping()
     {
         ManyToOne(x => x.Customer, map => map.Column("CustomerId"));
         Property(x => x.EmissionDay, map => map.Type(NHibernateUtil.Date));
         Bag(x => x.Items, map => map.Key(km => km.Column("OrderId")));
     }
 }
public class OrderItemMapping : EntityMapping<OrderItem>
 {
     public OrderItemMapping()
     {
         ManyToOne(x => x.Order, map => map.Column("OrderId"));
         Property(x => x.Product);
         Property(x => x.Price);
     }
 }

Adicionando mapeamentos ao ModelMapper:
Uma das formas de se aplicar o mapeamento é utilizando a classe ModelMapper.

var mapper = new ModelMapper();
 mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());
HbmMapping mapeamentoDominio = mapper.CompileMappingForAllExplicitlyAddedEntities();

E é só, agora e só adicionar o mapeamentoDominio ao objeto de configuração do NHibernate antes de construir a factory de sessões utilizando o BuildSessionFactory.

var configuration = new Configuration();
 configuration.DataBaseIntegration(c =>
 {
     c.Dialect<MsSql2008Dialect>();
     c.ConnectionString = @"Data Source=localhost\SQLEXPRESS;Initial Catalog=IntroNH;Integrated Security=True;Pooling=False";
     c.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
     c.SchemaAction = SchemaAutoAction.Create; // Recria a estrutura do banco automaticamente.
 });
 configuration.AddMapping(mapeamentoDominio);

var factory = configuration.BuildSessionFactory();
Guia Ecológico

Despertando a consciência que preserva!

Viagem e Voo

Dicas para viagens, férias e voos nacionais e internacionais

Ivan Guimarães Meirelles

Analista Desenvolvedor

Void Podcast

Vazio e sem retorno de valor

Elemar DEV

Negócios, tecnologia e desenvolvimento

2,000 Things You Should Know About WPF

Everything a WPF Developer Needs to Know, in Bite-Sized Chunks

Gabriel RB.net

Blog técnico, com dicas, códigos, novidades e problemas do dia-a-dia programando.

Alexandre Valente's Blog

Experiências em tecnologia e assuntos diversos

%d blogueiros gostam disto: