Include_in_parent using Nest elastic search library - c#

Is the IncludeInParent elastic property available in NEST C# like they have it for IncludeInAll.
If yes then how we add the IncludeInParent property to the objects.
I don't want to use fluent mapping as my index creating class is dynamic for an e.g:
public ESClient CreateIndex<T>() where T : class
{
if (!Client.IndexExists(f => f.Index(ESIndexName)).Exists)
{
Client.CreateIndex(ESIndexName, c => c
.NumberOfReplicas(1)
.NumberOfShards(4)
.Settings(s => s
.Add("merge.policy.merge_factor", "10")
.Add("search.slowlog.threshold.fetch.warn", "1s")
)
.AddMapping<T>(m => m.MapFromAttributes())
);
}
return this;
}
Is there a way I can specify IncludeInParent like IncludeInAll as below:
[ElasticProperty(IncludeInAll = true)]
public List<Cars> Cars { get; set; }
If not I think its nice to add IncludeInParent elastic property in NEST library.

What you ask can only be done using the fluent api.
The reply in this post Include_In_Parent option for ElasticSearch and NEST library may help you.

Related

MongoDB C# 2.x Driver ElemMatch with Dictionaries

I am trying to use ElemMatch to find a document in MongoDB using the 2.2 driver with no success. I am receiving an exception such as:
System.InvalidOperationException : The serializer for field
'EnabledForProduct' must implement IBsonArraySerializer and provide
item serialization info.
Here's how my class looks like:
public class Document
{
public string Id {get; set;}
public Dictionary<Product, bool> EnabledForProduct { get; set; }
}
public enum Product {Product1,Product2};
My ClassMap looks lke this:
BsonClassMap.RegisterClassMap<Document>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.EnabledForProduct)
.SetSerializer(new DictionaryInterfaceImplementerSerializer<Dictionary<Product, bool>>(DictionaryRepresentation.ArrayOfDocuments,
BsonSerializer.LookupSerializer<int>(),
BsonSerializer.LookupSerializer<bool>()));
});
The exception occurs when trying to use a Filter such as:
Builders<Document>.Filter.ElemMatch(f => f.EnabledForProduct,
x => x.Key == Product1 && x.Value))
This used to work flawlessly in the 1.x Driver.
Does anyone know what I am doing wrong?
Well, after some trial and error implementations, I figured out a way to do what I needed. Instead of directly using my model class, I ended up using a BsonDocument collection just for my ElemMatch filter like this:
var bsonCollection = database.GetCollection<BsonDocument>("testcollection");
The filter gets created like this:
var filter = Builders<BsonDocument>.Filter.ElemMatch("EnabledForProduct", Builders<BsonDocument>.Filter.And(Builders<BsonDocument>.Filter.Eq("k",(int)Product.Product1),Builders<BsonDocument>.Filter.Eq("v",true)));
And the generic BsonDocument can be deserialized back to my model class using BsonSerializer:
var foundDoc = BsonSerializer.Deserialize<Document>(bsonCollection.Find(filter).Limit(1).FirstOrDefault());

NHibernate programmatically mapping

I want to create a custom mapping standard so I don't have to create the map.cs file for all new classes in the project.
public class Person
{
public int PersonID { get; set; }
public string Name { get; set; }
}
Usually I'd have this:
public class PersonMap : ClassMapping<Person>
{
public PersonMap()
{
Table("Person");
Id(p => p.PersonID, map =>
{
map.Column("PersonID");
map.Generator(Generators.Identity);
});
Property(p => p.Name, map => map.Column("Name"));
}
}
I'd like to dynamically create these mappings based on some standards using reflection.
public class GenericDAL<T> where T : class, new()
{
public GenericDAL()
{
Configuration hConfig = new Configuration();
hConfig.DatabaseIntegration(c =>
{
c.ConnectionStringName = "myConnectionStringName";
c.Dialect<MsSql2012Dialect>();
});
ModelMapper mapper = new ModelMapper();
//Dynamic Mapping here
ISessionFactory _sessionFactory = hConfig.BuildSessionFactory();
}
}
I don't know how I can create a new ClassMapping from my T, how can I do this?
#SteveLillis already answered the question in the comments that there are already solutions for this.
Both MappingByCode in NHibernate (see below) and FluentNHibernate support automapping with conventions and overrides.
Links for Mapping By Code copied from original Answer which is not available anymore
First impressions
Naming convention resembling Fluent
Property
Component
ManyToOne
inheritance
dynamic component
Set and Bag
OneToMany and other collection-based relation types
concurrency
OneToOne
Join
Any
List, Array, IdBag
Map
Id, NaturalId
composite identifiers
entity-level mappings
the summary
I was looking for the same thing and I found a great documentation on NHibernate official website.
Here we have all the links to "fabiomaulo.blogspot" website, there you will find what are you looking for, WITHOUT FluentNHibernate.
Good Luck

Reusable Calculations For LINQ Projections In Entity Framework (Code First)

My domain model has a lot of complex financial data that is the result of fairly complex calculations on multiple properties of various entities. I generally include these as [NotMapped] properties on the appropriate domain model (I know, I know - there's plenty of debate around putting business logic in your entities - being pragmatic, it just works well with AutoMapper and lets me define reusable DataAnnotations - a discussion of whether this is good or not is not my question).
This works fine as long as I want to materialize the entire entity (and any other dependent entities, either via .Include() LINQ calls or via additional queries after materialization) and then map these properties to the view model after the query. The problem comes in when trying to optimize problematic queries by projecting to a view model instead of materializing the entire entity.
Consider the following domain models (obviously simplified):
public class Customer
{
public virtual ICollection<Holding> Holdings { get; private set; }
[NotMapped]
public decimal AccountValue
{
get { return Holdings.Sum(x => x.Value); }
}
}
public class Holding
{
public virtual Stock Stock { get; set; }
public int Quantity { get; set; }
[NotMapped]
public decimal Value
{
get { return Quantity * Stock.Price; }
}
}
public class Stock
{
public string Symbol { get; set; }
public decimal Price { get; set; }
}
And the following view model:
public class CustomerViewModel
{
public decimal AccountValue { get; set; }
}
If I attempt to project directly like this:
List<CustomerViewModel> customers = MyContext.Customers
.Select(x => new CustomerViewModel()
{
AccountValue = x.AccountValue
})
.ToList();
I end up with the following NotSupportedException: Additional information: The specified type member 'AccountValue' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Which is expected. I get it - Entity Framework can't convert the property getters into a valid LINQ expression. However, if I project using the exact same code but within the projection, it works fine:
List<CustomerViewModel> customers = MyContext.Customers
.Select(x => new CustomerViewModel()
{
AccountValue = x.Holdings.Sum(y => y.Quantity * y.Stock.Price)
})
.ToList();
So we can conclude that the actual logic is convertible to a SQL query (I.e., there's nothing exotic like reading from disk, accessing external variables, etc.).
So here's the question: is there any way at all to make logic that should be convertible to SQL reusable within LINQ to entity projections?
Consider that this calculation may be used within many different view models. Copying it to the projection in each action is cumbersome and error prone. What if the calculation changes to include a multiplier? We'd have to manually locate and change it everywhere it's used.
One thing I have tried is encapsulating the logic within an IQueryable extension:
public static IQueryable<CustomerViewModel> WithAccountValue(
this IQueryable<Customer> query)
{
return query.Select(x => new CustomerViewModel()
{
AccountValue = x.Holdings.Sum(y => y.Quantity * y.Stock.Price)
});
}
Which can be used like this:
List<CustomerViewModel> customers = MyContext.Customers
.WithAccountValue()
.ToList();
That works well enough in a simple contrived case like this, but it's not composable. Because the result of the extension is an IQueryable<CustomerViewModel> and not a IQueryable<Customer> you can't chain them together. If I had two such properties in one view model, one of them in another view model, and then the other in a third view model, I would have no way of using the same extension for all three view models - which would defeat the whole purpose. With this approach, it's all or nothing. Every view model has to have the exact same set of calculated properties (which is rarely the case).
Sorry for the long-winded question. I prefer to provide as much detail as possible to make sure folks understand the question and potentially help others down the road. I just feel like I'm missing something here that would make all of this snap into focus.
I did a lot of research on this the last several days because it's been a bit of a pain point in constructing efficient Entity Framework queries. I've found several different approaches that all essentially boil down to the same underlying concept. The key is to take the calculated property (or method), convert it into an Expression that the query provider knows how to translate into SQL, and then feed that into the EF query provider.
I found the following libraries/code that attempted to solve this problem:
LINQ Expression Projection
http://www.codeproject.com/Articles/402594/Black-Art-LINQ-expressions-reuse and http://linqexprprojection.codeplex.com/
This library allows you to write your reusable logic directly as an Expression and then provides the conversion to get that Expression into your LINQ query (since the query can't directly use an Expression). The funny thing is that it'll be translated back to an Expression by the query provider. The declaration of your reusable logic looks like this:
private static Expression<Func<Project, double>> projectAverageEffectiveAreaSelector =
proj => proj.Subprojects.Where(sp => sp.Area < 1000).Average(sp => sp.Area);
And you use it like this:
var proj1AndAea =
ctx.Projects
.AsExpressionProjectable()
.Where(p => p.ID == 1)
.Select(p => new
{
AEA = Utilities.projectAverageEffectiveAreaSelector.Project<double>()
});
Notice the .AsExpressionProjectable() extension to set up projection support. Then you use the .Project<T>() extension on one of your Expression definitions to get the Expression into the query.
LINQ Translations
http://damieng.com/blog/2009/06/24/client-side-properties-and-any-remote-linq-provider and https://github.com/damieng/Linq.Translations
This approach is pretty similar to the LINQ Expression Projection concept except it's a little more flexible and has several points for extension. The trade off is that it's also a little more complex to use. Essentially you still define your reusable logic as an Expression and then rely on the library to convert that into something the query can use. See the blog post for more details.
DelegateDecompiler
http://lostechies.com/jimmybogard/2014/05/07/projecting-computed-properties-with-linq-and-automapper/ and https://github.com/hazzik/DelegateDecompiler
I found DelegateDecompiler via the blog post on Jimmy Bogard's blog. It has been a lifesaver. It works well, is well architected, and requires a lot less ceremony. It does not require you to define your reusable calculations as an Expression. Instead, it constructs the necessary Expression by using Mono.Reflection to decompile your code on the fly. It knows which properties, methods, etc. need to be decompiled by having you decorate them with ComputedAttribute or by using the .Computed() extension within the query:
class Employee
{
[Computed]
public string FullName
{
get { return FirstName + " " + LastName; }
}
public string LastName { get; set; }
public string FirstName { get; set; }
}
This can also be easily extended, which is a nice touch. For example, I set it up to look for the NotMapped data annotation instead of having to explicitly use the ComputedAttribute.
Once you've set up your entity, you just trigger decompilation by using the .Decompile() extension:
var employees = ctx.Employees
.Select(x => new
{
FullName = x.FullName
})
.Decompile()
.ToList();
You can encapsulate logic by creating a class that contains the original Entity and the additional calculated property. You then create helper methods that project to the class.
For example, if we were trying to calculate the tax for an Employee and a Contractor entity, we could do this:
//This is our container for our original entity and the calculated field
public class PersonAndTax<T>
{
public T Entity { get; set; }
public double Tax { get; set; }
}
public class PersonAndTaxHelper
{
// This is our middle translation class
// Each Entity will use a different way to calculate income
private class PersonAndIncome<T>
{
public T Entity { get; set; }
public int Income { get; set; }
}
Income calculating methods
public static IQueryable<PersonAndTax<Employee>> GetEmployeeAndTax(IQueryable<Employee> employees)
{
var query = from x in employees
select new PersonAndIncome<Employee>
{
Entity = x,
Income = x.YearlySalary
};
return CalcualateTax(query);
}
public static IQueryable<PersonAndTax<Contractor>> GetContratorAndTax(IQueryable<Contractor> contractors)
{
var query = from x in contractors
select new PersonAndIncome<Contractor>
{
Entity = x,
Income = x.Contracts.Sum(y => y.Total)
};
return CalcualateTax(query);
}
Tax calculation is defined in one place
private static IQueryable<PersonAndTax<T>> CalcualateTax<T>(IQueryable<PersonAndIncome<T>> personAndIncomeQuery)
{
var query = from x in personAndIncomeQuery
select new PersonAndTax<T>
{
Entity = x.Entity,
Tax = x.Income * 0.3
};
return query;
}
}
Our view model projections using the Tax property
var contractorViewModel = from x in PersonAndTaxHelper.GetContratorAndTax(context.Contractors)
select new
{
x.Entity.Name,
x.Entity.BusinessName
x.Tax,
};
var employeeViewModel = from x in PersonAndTaxHelper.GetEmployeeAndTax(context.Employees)
select new
{
x.Entity.Name,
x.Entity.YearsOfService
x.Tax,
};

Collate two collections using Automapper

I am looking around for a tool to automate the collation of two collections into each other and I think Automapper should work for this. We have many instances of this operation and I would like to centralize this logic into a single area.
I have the following two classes:
public class Product
{
public IEnumerable<Order> CurrentCustomerOrders { get;set; }
}
public class Order
{
order properties
}
And they are retrieved via the following calls:
_repo.GetTable<Product>();
_repo.GetTable<Order>().Where(n => n.CustomerId = _customerId);
What I want is to put all the Orders into the Products or something like this:
Mapper.CreateMap<IEnumerable<Order>, IEnumerable<Product>>()
.ForEachMember(n => n.CurrentCustomerOrders), opt => opt.MapFrom(p => p.Where(Order.ProductId == Product.ProductId))
How would I go about doing this using Automapper? Or do you know of a better tool to do this?
Thanks!
Usually you would do the filtering first using Linq or something and then do the mapping. Automapper is just a mapping tool.
e.g.
Product.CurrentCustomerOrders =
Mapper.Map<OrderDO, Order>(Orders.Where(o => o.ProductId == Product.ProductId));

NHibernate Mapping Property Beyond LINQ Querying

my application has the following entity:
public class User
{
public virtual int UserID { get; set; }
public virtual Membership LatestMembership { get { return Membership.First(); } }
public virtual IList<Membership> Membership { get; set; }
public User()
{
Membership = new List<Membership>();
}
}
With the following mapping:
public UserMap()
{
Table("Users");
Id(x => x.UserID);
HasMany(x => x.Membership)
.KeyColumn("UserID")
.OrderBy("DateAdded DESC")
.Inverse()
.Cascade.All();
}
The LatestMembership property against the user simply grabs the first record from the Membership collection (which is ordered so that the newer records are at the top).
So far so good, however now say i want to do the following (i know this will return them all but i'm just using this as an example):
var users = session.Linq<User>()
.Where(u => u.LatestMembership.DateAdded < DateTime.UtcNow);
An error is thrown because the LatestMembership property is beyond the nhibernate linq providers capabilities. The only solution i have so far is to convert it to a list and then apply the where condition but i'd imagine this could become pretty insuficient for a large database.
I was wondering if there was an alternative way i could map this or what your recommendations are. Thanks
Unfortunately, this isn't really possible using the current Linq provider. One thing you can do is to map the properties of the LatestMembership you want to query on as read-only and use formulas in your mappings to derive the values for it. You can see some further details in my answer to this post.
The other possible solution is to attack this from the Membership side of things; query for the latest membership matching the user in question and filter accordingly.

Categories

Resources