NHibernate vs LINQ to SQL


117

Como alguém que não usou nenhuma das tecnologias em projetos do mundo real, eu me pergunto se alguém sabe como essas duas se complementam e o quanto suas funcionalidades se sobrepõem?

Respostas:


113

LINQ to SQL força você a usar o padrão tabela por classe. Os benefícios de usar esse padrão são que ele é rápido e fácil de implementar e exige muito pouco esforço para colocar seu domínio em execução com base em uma estrutura de banco de dados existente. Para aplicativos simples, isso é perfeitamente aceitável (e muitas vezes até preferível), mas para aplicativos mais complexos, os desenvolvedores geralmente sugerem o uso de um padrão de design orientado por domínio (que é o que o NHibernate facilita).

O problema com o padrão tabela por classe é que a estrutura do banco de dados tem uma influência direta sobre o design do domínio. Por exemplo, digamos que você tenha uma tabela Clientes com as seguintes colunas para conter as informações do endereço principal de um cliente:

  • Endereço
  • Cidade
  • Estado
  • Fecho eclair

Agora, digamos que você também queira adicionar colunas para o endereço de correspondência do cliente, então adicione as seguintes colunas à tabela Clientes:

  • MailingStreetAddress
  • MailingCity
  • MailingState
  • MailingZip

Usando LINQ to SQL, o objeto Customer em seu domínio agora teria propriedades para cada uma dessas oito colunas. Mas se você estivesse seguindo um padrão de design orientado por domínio, provavelmente teria criado uma classe Address e sua classe Customer manteria duas propriedades Address, uma para o endereço de correspondência e outra para o endereço atual.

Esse é um exemplo simples, mas demonstra como o padrão tabela por classe pode levar a um domínio um tanto fedorento. No final, depende de você. Novamente, para aplicativos simples que precisam apenas da funcionalidade CRUD (criar, ler, atualizar, excluir) básica, o LINQ to SQL é ideal por causa da simplicidade. Mas pessoalmente gosto de usar o NHibernate porque facilita um domínio mais limpo.

Edit: @lomaxx - Sim, o exemplo que usei era simplista e poderia ter sido otimizado para funcionar bem com LINQ to SQL. Eu queria mantê-lo o mais básico possível para esclarecer o ponto. A questão permanece, porém, que existem vários cenários em que ter sua estrutura de banco de dados determinando sua estrutura de domínio seria uma má ideia, ou pelo menos levaria a um projeto OO abaixo do ideal.


4
Você pode codificar a implementação de seu repositório usando Linq To SQL, é muito útil.
Nicolas Dorier

1
Acho que não é ActiveRecord, mesmo as classes mapeadas encapsulam parte da lógica da infraestrutura. O padrão ActiveRecord seria se você pudesse ter Customer.Save (). L2S implementa o padrão Unit of Work com a classe DataContext, como Session em nHibernate, mas NH tem uma abordagem POCO real.
Hrvoje Hudo

1
@kevin "LINQ to SQL usa o padrão de registro ativo" Incorreto. É como dizer que o ADO.NET usa o registro ativo ou o NHibernate usa o registro ativo. Todas são tecnologias de acesso a dados e não impõem nenhum padrão específico de acesso a dados. Pessoalmente, gosto de usar linq-to-sql com o padrão de repositório. Você está correto que linq-to-sql não suporta mapeamentos complexos como o NHibernate.
liammclennan

1
Que tal normalizar seu banco de dados e deixar seu DAL ser gerado por ferramentas, por exemplo, SQLMetal?
Alex

3
@CoffeeAddict Quando a diferença de impedância é demais para suportar, é quando seu aplicativo é muito complicado de usar LINQ to SQL, imo. O motivo do meu exemplo ser fedorento é porque o uso de LINQ to SQL resultaria em 8 propriedades em vez de 2 e restringe sua capacidade de fazer coisas como implementar funções que usam uma classe Address ou implementar rotinas na classe Address que você seria capaz de fazer fazer se você tiver usado NHibernate.
Kevin Pang

26

Dois pontos que foram perdidos até agora:

  • LINQ to SQL não funciona com Oracle ou qualquer banco de dados além do SqlServer. No entanto, terceiros oferecem melhor suporte para Oracle, por exemplo, devArt's dotConnect , DbLinq , Mindscape's LightSpeed e ALinq . (Não tenho nenhuma experiência pessoal com estes)

  • O Linq para NHibernate permite que você use o Linq com um Nhiberate, portanto, pode haver um motivo para não usar.

Além disso, a nova interface fluente do Nhibernate parece tornar menos doloroso configurar o mapeamento do Nhibernate. (Removendo um dos pontos fracos do Nhibernate)


Atualizar

Linq para Nhiberate é melhor no Nhiberate v3 que agora está em alfa . Parece que o Nhiberate v3 pode ser lançado no final deste ano.

O Entity Frame Work a partir do .net 4 também está começando a parecer uma opção real.


2
Linq para NHibernate ainda está em um estágio muito inicial. Não é uma implementação completa e, sem dúvida, não está pronta para uso em produção.
liammclennan

A nova versão do LinqConnect 2.0 introduz alguns recursos adicionais para conveniência, como suporte de herança de Tabela por Tipo, suporte de PLINQ e a funcionalidade de Atualizações em Lote. ORM Designer (Devart Entity Developer) agora tem suporte para Model First e recurso de Sincronização de Mapeamento. Mais detalhes: devart.com/news/2010/dotconnects600.html
Devart

23

@ Kevin: Acho que o problema com o exemplo que você está apresentando é que você está usando um design de banco de dados ruim. Eu pensei que você criaria uma tabela de clientes e uma tabela de endereços e normalizaria as tabelas. Se você fizer isso, poderá usar definitivamente o Linq To SQL para o cenário que está sugerindo. Scott Guthrie tem uma ótima série de posts sobre como usar o Linq To SQL que eu sugiro fortemente que você dê uma olhada.

Eu não acho que você poderia dizer que Linq e NHibernate se complementam, já que isso implicaria que eles poderiam ser usados ​​juntos e, embora isso seja possível, é muito melhor escolher um e mantê-lo.

NHibernate permite mapear suas tabelas de banco de dados para seus objetos de domínio de uma forma altamente flexível. Ele também permite que você use o HBL para consultar o banco de dados.

Linq para SQL também permite que você mapeie seus objetos de domínio para o banco de dados, no entanto, ele usa a sintaxe de consulta Linq para consultar o banco de dados

A principal diferença aqui é que a sintaxe da consulta Linq é verificada no tempo de compilação pelo compilador para garantir que suas consultas sejam válidas.

Algumas coisas a serem observadas com o linq é que ele está disponível apenas em .net 3.xe é compatível apenas com o VS2008. NHibernate está disponível em 2.0 e 3.x, bem como em VS2005.

Algumas coisas a serem observadas com o NHibernate é que ele não gera seus objetos de domínio, nem gera os arquivos de mapeamento. Você precisa fazer isso manualmente. O Linq pode
fazer isso automaticamente para você.


15
E se você estiver escrevendo código em uma estrutura de banco de dados legado que não pode ser alterada porque oferece suporte a outros aplicativos. Você deseja que seu modelo de domínio herde o design de banco de dados deficiente ou deseja criar um modelo de domínio rico que pode variar independentemente da estrutura do banco de dados?
Larry Foulkrod,

7

O Fluent NHibernate pode gerar seus arquivos de mapeamento com base em convenções simples. Sem gravação de XML e fortemente tipado.

Recentemente, trabalhei em um projeto em que precisávamos mudar de Linq para SQL para NHibernate por motivos de desempenho. Especialmente a maneira do L2S de materializar os objetos parece mais lenta do que a idem do NHibernate e o gerenciamento de mudanças também é bastante lento. E pode ser difícil desativar o gerenciamento de mudanças em cenários específicos onde ele não é necessário.

Se você for usar suas entidades desconectadas do DataContext - em cenários WCF, por exemplo - você pode ter muitos problemas para conectá-las ao DataContext novamente para atualizar as alterações. Não tive problemas com isso com o NHibernate.

O que vou sentir falta do L2S é principalmente a geração de código que mantém as relações atualizadas em ambas as extremidades das entidades. Mas acho que existem algumas ferramentas para o NHibernate fazer isso por aí também ...


2
Apenas no caso de outras pessoas lerem sua postagem e também pensarem em abandonar o navio - .ObjectTrackingEnabled = falsevocê DataContextteria resolvido o problema de rastreamento de alterações. Contanto que você adote o padrão de unidade de trabalho e não esteja procurando fazer DDD, o Linq-to-SQL realmente cumpre.
mattmc3

" Precisamos mudar de Linq para SQL para NHibernate por motivos de desempenho " - Tendo usado [Fluent, não menos] NHibernate por alguns anos, sinto por você. Acho que trapaceamos principalmente e acabamos escrevendo SQL nativo para pontos de pressão de desempenho reais. Seria interessante ouvir uma atualização (seis anos depois ...) sobre como foi sua migração e se valeu a pena.
ruffin,

5

Você pode esclarecer o que quer dizer com "LINQ"?

LINQ não é uma tecnologia de acesso a dados, é apenas um recurso de linguagem que oferece suporte a consultas como uma construção nativa. Ele pode consultar qualquer modelo de objeto que suporte interfaces específicas (por exemplo, IQueryable).

Muitas pessoas se referem a LINQ To SQL como LINQ, mas isso não é correto. A Microsoft acaba de lançar o LINQ To Entities com .NET 3.5 SP1. Além disso, o NHibernate tem uma interface LINQ, então você pode usar o LINQ e o NHibernate para obter seus dados.


2

Por LINQ, estou supondo que você quer dizer LINQ to SQL porque o LINQ, por si só, não tem nenhum banco de dados "em andamento" associado a ele. É apenas uma linguagem de consulta que tem um monte de açúcar syntac para fazer com que pareça SQL.

No básico dos exemplos básicos, NHibernate e LINQ to SQL parecem estar resolvendo o mesmo problema. Depois de passar, você logo percebe que o NHibernate tem suporte para muitos recursos que permitem criar modelos de domínio verdadeiramente ricos. Há também um projeto LINQ to NHibernate que permite usar LINQ para consultar o NHibernate da mesma forma que você usaria LINQ to SQL.


1

Primeiro, vamos separar duas coisas diferentes: a modelagem de banco de dados se preocupa com os dados, enquanto a modelagem de objetos se preocupa com entidades e relacionamentos.

A vantagem do Linq para SQL é gerar rapidamente classes fora do esquema do banco de dados para que possam ser usadas como objetos de registro ativo (consulte a definição do padrão de design do registro ativo).

A vantagem do NHibernate é permitir flexibilidade entre a modelagem de objetos e a modelagem de banco de dados. O banco de dados pode ser modelado para melhor refletir seus dados, levando em consideração o desempenho, por exemplo. Embora sua modelagem de objetos reflita melhor os elementos da regra de negócios usando uma abordagem como Domain-Driven-Design. (veja o comentário de Kevin Pang)

Com bancos de dados legados com modelagem pobre e / ou convenções de nomenclatura, o Linq-to-SQL refletirá essas estruturas e nomes indesejados para suas classes. No entanto, o NHibernate pode esconder essa bagunça com mapeadores de dados.

Em projetos novos em que os bancos de dados têm boa nomenclatura e baixa complexidade, o Linq-to-SQL pode ser uma boa escolha.

No entanto, você pode usar o Fluent NHibernate com mapeamentos automáticos para o mesmo propósito com o mapeamento por convenção. Neste caso, você não se preocupa com nenhum mapeador de dados com XML ou C # e deixe o NHibernate gerar o esquema do banco de dados de suas entidades com base em uma convenção que você pode personalizar.

Por outro lado, a curva de aprendizado do Linq-to-SQL é menor que o NHibernate.


0

Ou você pode usar o projeto Castle ActiveRecords. Estou usando isso há um curto período de tempo para desenvolver um novo código para um projeto legado. Ele usa NHibernate e funciona no padrão de registro ativo (surpreendente dado o nome que eu conheço). Eu não tentei, mas suponho que uma vez que você o tenha usado, se você sentir a necessidade de recorrer diretamente ao suporte do NHibernate, não seria demais fazê-lo para parte ou todo o seu projeto.


0

Como você escreveu "para uma pessoa que não usou nenhum deles", o LINQ to SQL é fácil de usar, então qualquer um pode usá-lo facilmente. Ele também oferece suporte a procedimentos, o que ajuda na maioria das vezes. Suponha que você queira obter dados de mais de uma tabela, em seguida, escreva um procedimento e arraste esse procedimento para o designer e ele criará tudo para você. Suponha que o nome do seu procedimento seja "CUSTOMER_ORDER_LINEITEM", que busca o registro de todas essas três tabelas e, em seguida, basta escrever

MyDataContext db = new MyDataContext();
List<CUSTOMER_ORDER_LINEITEMResult> records = db.CUSTOMER_ORDER_LINEITEM(pram1, param2 ...).ToList<CUSTOMER_ORDER_LINEITEMResult>();

você pode usar o objeto de registros no loop foreach também, que não é suportado pelo NHibernate

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.