Lançado: Linq2Couchbase v1.1.0, o provedor oficial de Linq para o Couchbase N1QL!
No início desta semana, lançamos a v1.1.0 (especificamente a v1.1.0.2) do Linq2Couchbase, o provedor oficial de Linq para o Couchbase Server e N1QL! Esta versão inclui recursos novos e experimentais, bem como correções de bugs e muitos, muitos aprimoramentos em relação à versão 1.0.X. Nesta postagem, discutiremos e demonstraremos os novos recursos quando aplicável!
Contribuintes
O Linq2Couchbase é um projeto orientado pela comunidade, o número um contribuinte (obrigado Brant!) é um membro da comunidade! Se você quiser contribuir ou enviar comentários, sinta-se à vontade para fazê-lo na seção projeto no github ou o Projeto Jira.
Principais recursos e/ou confirmações
Mais de 30 commits foram incluídos nessa versão, incluindo os seguintes recursos:
- Compatibilidade com serializadores personalizados estendendo o IExtendedTypeSerializer
- Suporte a funções de data, como DATE_DIFF, DATE_ADD, DATE_PART e DATE_TRUNC
- Suporte para operações Contains em matrizes
- Suporte para enumeração e constantes GUID em consultas
- Suporte para instruções UNION
- Documentação XML em linha aprimorada
- Suporte para consultas LINQ assíncronas usando .ExecuteAsync
- Suporte para especificar o nível de consistência da consulta para RYOW
- Tratamento de erros aprimorado
- Diversas correções de bugs
Nos próximos parágrafos, discutirei alguns dos recursos mais importantes/úteis.
Controle de alterações e proxy
Um novo recurso "experimental" que adicionamos à versão 1.1.0 é o suporte ao rastreamento de alterações por meio de objetos proxy. O caso de uso desse recurso é supor que você gostaria de modificar ou adicionar vários documentos, mas deseja que a mutação ocorra em lote em um momento posterior. Por exemplo, você deseja que o objeto BucketContext tenha a vida útil de uma solicitação da Web no ASP.NET: quando a solicitação começa, você deseja que o contexto seja criado, dentro de qualquer método de ação que você queira modificar ou adicionar documentos e, finalmente, quando a solicitação terminar, você deseja enviar tudo de volta ao servidor... ou reverter se ocorrer um erro.
O controle de alterações é ativado chamando o BucketContext.EnableChangeTracking() método antes de iniciando uma consulta.
|
1 2 3 4 5 6 7 |
var db = new BucketContext(ClusterHelper.GetBucket("beer-sample")); db.BeginChangeTracking(); var query = from x in db.Query() where x.Type == "beer" select x; |
Uma vez que ele é chamado de BucketContext interceptará cada linha do conjunto de resultados e criará um proxy dinâmico que fará com que todas as alterações nas propriedades ou nas propriedades dos documentos filhos voltem para o BucketContext.
Por exemplo, suponha que desejemos recuperar o primeiro documento da lista e modificar a propriedade Abv:
|
1 2 3 |
var beer = query.First(); beer.Abv = new decimal(12.6); |
Quando a propriedade Abv for definido, ele acionará um evento que irá borbulhar até o BucketContext que armazenará uma referência ao documento modificado. A atualização real não ocorrerá no Couchbase até mais tarde, quando SubmitChanges é chamado.
E quanto a adicionar um novo documento? Nesse caso, você criaria o documento normalmente e, em seguida, chamaria Salvar no BucketContext:
|
1 2 3 4 5 6 7 8 9 |
var newBeer = new Beer { Abv = 5, Category = "ale", Name = "Some Brew" }; db.Save(newBeer); |
A chamada para db.Save é necessário para que o novo documento (que não é uma procuração) possa ser embrulhado em um proxy e rastreado. Finalmente, quando queremos enviar as alterações de volta ao servidor, chamamos SubmitChanges:
|
1 2 |
db.SubmitChanges(); |
Aguarde um exemplo muito mais detalhado em uma publicação futura, na qual criaremos um aplicativo ASP.NET MVC e mostraremos como o BucketContext pode ser usado em um controlador ASP.NEW como uma unidade de trabalho (UoW) com escopo para a solicitação da Web.
Serializadores personalizados por meio do IExtendedTypeSerializer
Há algum tempo, o SDK do Couchbase .NET oferece suporte a serializadores personalizados. O serializador padrão é baseado no NewtonSoft JSON.NET, que é um serializador completo e bem suportado; no entanto, em alguns casos, você pode querer usar outro serializador, como o Jil ou Pilha de serviços's Text. Para oferecer suporte a outros serializadores JSON que não sejam da NewtonSoft em Linq2CouchbaseAdicionamos uma nova interface chamada IExtendedTypeSerializer. Além disso, o mecanismo de serialização foi estendido para incluir o QueryRequest como um ponto de integração, o que significa que um serializador personalizado pode ser usado por solicitação, em vez de uniformemente em todo o Couchbase .NET SDK.
Suporte para funções de data N1QL
O N1QL oferece suporte a muitas funções Date que não se traduzem diretamente em métodos DateTime do .NET. Nesta versão, adicionamos suporte a várias dessas funções Função de data N1QLs incluindo:
- DATE_DIFF_STR
- DATE_ADD_STR
- DATE_PART_STR
- DATE_TRUNC_STR
Além disso, foi adicionada uma nova enumeração chamada N1QLDatePart para o parâmetro de parte da data aceito por cada função. Você pode ler mais sobre como trabalhar com datas aqui.
Atualize para o Relinq 2.0 e use o ILRepack
Relinqa biblioteca de código aberto que o Linq2Couchbase (NHibernate e Estrutura de entidades 7 também) lançou recentemente a versão 2.0, portanto, atualizamos para a mais recente. Para facilitar o uso do Linq2Couchbase com o EF 7 no mesmo projeto e reduzir o número de dependências necessárias, o Relinq (e o Castelo.Core) foram mescladas no momento da compilação usando ILRepack no pacote NuGet.
Suporte para UNIÃO e UNION ALL Declarações
Para combinar os resultados de mais duas consultas em um único conjunto de resultados, o N1QL tem dois comandos especiais: UNIÃO e UNION ALL.
UNION retorna os resultados distintos de cada consulta e agora é compatível com o Linq2Couchbase. Por exemplo, a seguinte consulta Linq:
|
1 2 3 4 5 6 7 8 |
var query = db.Query(mockBucket.Object) .Where(e => e.Type == "beer") .Select(e => new { e.Name }) .Union( db.QueryBrewery>(mockBucket.Object) .Where(e => e.Type == "brewery") .Select(e => new { e.Name })); |
Será gerada em uma consulta N1QL semelhante a esta:
|
1 2 3 4 |
SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer') UNION SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery'); |
UNION ALL retorna duplicatas e a sintaxe do Linq é um pouco diferente, pois usamos o método Concat:
|
1 2 3 4 5 6 7 8 |
var query = db.Query(mockBucket.Object) .Where(e => e.Type == "beer") .Select(e => new { e.Name }) .Concat( db.Query(mockBucket.Object) .Where(e => e.Type == "brewery") .Select(e => new { e.Name })); |
A consulta N1QL emitida terá a seguinte aparência:
|
1 2 3 4 |
SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer' UNION ALL SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery' |
Observe que vários UNIÃOs também podem ser aplicados!
Consultas assíncronas de Linq
Outro recurso interessante que foi adicionado é o suporte a consultas Linq assíncronas usando o assíncrono e aguardar que são incorporados ao C#/.NET. Observe que há suporte para IEnumerable e escalar (Sum, First(), Any()).
Aqui está um exemplo que retorna um valor IEnumerable:
|
1 2 3 4 5 |
var beers = from b in context.Query() select b; var results = (await beers.Take(1).ExecuteAsync()).ToList(); |
Aqui está outro exemplo que demonstra a execução de um valor escalar:
|
1 2 3 4 5 |
var beers = from b in context.Query() select b; var result = await beers.ExecuteAsync(p => p.Average(q => q.Abv)); |
Em ambos os casos, a solicitação de consulta será executada de forma não bloqueada (como um pool de threads). Coisas legais.
Como obtê-lo
Você pode obter a versão 1.1.0 do Linq2Couchbase: