Making object models in solution based on third party ElasticSearch solution - c#

When you deal with JSON, it's really easy to make C# models. You either Paste special in Visual Studio, or you use one of the many available tools online.
ElasticSearch responses obviously are JSON, meaning, if you can get the responding JSON, you're good to go. However, if you just have a connection-string and simply want to "map" all the ElasticSearch objects into your C# code - how do you do it?
My question:
Is there a way to see all fields/data in an ElasticSearch instance, and then easily get the JSON, so you can get strongly typed models?

You can query elasticsearch for mappings. Mapping will contain all information you need to build model in C# (but you will still have to build it by hand I think). Example using database from your previous question:
var settings = new ConnectionSettings(new Uri("http://distribution.virk.dk/cvr-permanent"));
var client = new ElasticClient(settings);
// get mappings for all indexes and types
var mappings = client.GetMapping<JObject>(c => c.AllIndices().AllTypes());
foreach (var indexMapping in mappings.Indices) {
Console.WriteLine($"Index {indexMapping.Key.Name}"); // index name
foreach (var typeMapping in indexMapping.Value.Mappings) {
Console.WriteLine($"Type {typeMapping.Key.Name}"); // type name
foreach (var property in typeMapping.Value.Properties) {
// property name and type. There might be more useful info, check other properties of `typeMapping`
Console.WriteLine(property.Key.Name + ": " + property.Value.Type);
// some properties are themselves objects, so you need to go deeper
var subProperties = (property.Value as ObjectProperty)?.Properties;
if (subProperties != null) {
// here you can build recursive function to get also sub-properties
}
}
}
}

Related

Expression builder + Reflection?

I have a rather extensive view that needs to pull info for some kind of "search engine".
I access this view through Entity framework (with the use of a repository). I use a class name searchprops that contains 2 strings, a propertyName, and a property value.
Allow me to demonstrate the problem I am struggling with. In my head, the following solution should have worked, Using the "propertyName" value and utilise reflection to fill the correct property with the correct value, Like sending "vin", "123", should have built where X.Vin == 123...
Ofcourse, This triggers an error stating sql to entities can not be used with reflection, and this just baffles me.... Would somebody please point me in the right direction?
(explicitly setting a property does work however. so not all of the code is bad atleast, Its just reflection.)
public List<vw_AdHocReporting> GetDataFromView(IDictionary<string, string> actualValuesDictionary)
{
var searchprops = actualValuesDictionary.Select(keypair => new SearchProp {PropertyName = keypair.Key, PropertyValue = keypair.Value}).ToList();
var predicate = PredicateBuilder.New<vw_AdHocReporting>();
foreach (var prop in searchprops)
{
predicate = predicate.Or(p => p.GetType().GetProperty(prop.PropertyName).Name.Contains(prop.PropertyValue));
}
var query = context.vw_AdHocReporting.AsExpandable().Where(predicate).ToList();
return query;
}

HazelCast .NET - Clear Maps dynamically

I'm creating several maps to cache some info for my application.
When some events are triggered I want to clear those caches.
I have a list of all maps names I should clear but I couldn't find a way to dynamically get those maps in order to clear them. Basically I have:
var mapsNames = ["map-1", "map-2", "map-3"];
And I want a simple way of doing things like:
var client = HazelcastClient.NewHazelcastClient();
foreach (var name in mapsNames)
{
var map = client.GetMap(name);
map.Clear();
}
In the README.md we do have some examples like:
var client = HazelcastClient.NewHazelcastClient();
var personnelMap = client.GetMap("personnelMap");
personnelMap.Put("Alice", "IT");
personnelMap.Put("Bob", "IT");
personnelMap.Put("Clark", "IT");
Console.WriteLine("Added IT personnel. Logging all known personnel");
foreach(var entry in personnelMap.entrySet())
{
Console.WriteLine("{0} is in {1} department", entry.Key, entry.Value );
}
client.Shutdown();
That indicates we should have a method GetMap that is non-generic but I couldn't find it. The only one avaiable is GetMap<TKey, TValue>. Are the docs wrong? Is there a way to get a Map by its name without using some ugly reflection?
Thanks in advance,
Did you try (ICollection<IDistributedObject> GetDistributedObjects()) https://github.com/hazelcast/hazelcast-csharp-client/blob/v3.12.1/Hazelcast.Net/Hazelcast.Client/HazelcastClient.cs#L230 ?
You can iterate through all the existing maps, and you can use https://github.com/hazelcast/hazelcast-csharp-client/blob/v3.12.1/Hazelcast.Net/Hazelcast.Core/IDistributedObject.cs#L53 to check is the distributed object is of type map service.

C#, Generics, Type and NHibernate

I'm learning the power of generics in C# in conjunction with NHibernate. I'd like to attempt the following in the pasted code.
In an attempt to do some post processing of N number of NHibernate objects I worked on a utility method leveraging generics to make it applicable to all NHibernate mapping classes we use now, or in the future. It works but I need to hard code each call for each mapping class. This is a pain and will need continuing updating as our schema and mappings change over time.
I do have an ever up-to-date list of all mapping classes by string name through the NHibernate mappings I generate on the fly. If there was a way to use this list of string names to call my generics based method, I'd be super happy.
Can anyone tell me if this is possible? Do I need to find another route?
Thanks so much in advance!!!
public static void ProcessSomeItems()
{
// *************************************************************
// As of now I have to list all classes as such to be processed
// It works but I have to update manually when new mapping classes are created
// *************************************************************
NHibDoSomethingUtil<AspnetMembership>();
NHibDoSomethingUtil<AspnetProfile>();
NHibDoSomethingUtil<AspnetRole>();
NHibDoSomethingUtil<AspnetUser>();
// and so forth...
// I have a up-to-date list of all mappings from "HbmMapping" and can get a list of all in the
// list form as below
List<string> mappingNames = new List<string>();
foreach (string mappingName in mappingNames)
{
Type theType = Type.GetType(mappingName);
// I know I'm getting Types and Generics classes and so forth all jumbled but
// how in the heck would I do something like the below?
NHibDoSomethingUtil<theType>(); // Obviously doesn't compile ;-)
}
}
// Generic method
public static void NHibDoSomethingUtil<T>() where T : class
{
using (ISession session = sourceDBSessionFactory.OpenSession())
{
foreach (dynamic item in new List<T>(session.QueryOver<T>().List()))
{
// Process item;
}
}
}
ecsousa gave great input and I was able to accomplish what I needed with something like the following.
foreach (HbmClass mappingClass in mapping.Items)
{
Console.WriteLine(" -- Discovered Mapping: " + mappingClass.Name);
Type mappingClassType = Type.GetType(mappingClass.Name);
var genericMethod = typeof(Migration).GetMethod("NHibDoSomethingUtil");
var method = genericMethod.MakeGenericMethod(mappingClassType);
method.Invoke(null, null);
}
You will need to use Reflection in order to accomplish this. Instead of directly calling NHibDoSomethingUtil, try this:
var genericMethod = typeof(TheClassName).GetMethod("NHibDoSomethingUtil");
var method = genericMethod.MakeGenericMethod(theType);
method.Invoke(null, null);
Note that you have to replace TheClassName by the class containing both methods.
Keep in mind the this kind of code is slow, and you should use it very carefully.

NancyFx DynamicDictionary

I am trying to understand the DynamicDictionary in NancyFX, it looks pretty cool. Does anyone know of a blog post or similar, that goes through the internals of it?
I need a propertybag to pass around objects, that I don't know the content of because they come from outside my system as JSON. But based on the contents of these objects, such as the presence of certain properties I need to do stuff.
I could just pass around dynamic objects, but that is a bit too vague I think. Don't really like that.
I would need nested dictionaries, to fully represent the object graph.
The dynamic dictionary is just a ExpandoObject with a Dictionary in it. So it can still be accessed like a dictionary.
For example, in MVC you access Form properties like so:
var name = Request["name"];
or
var name = Request.Form["name"];
When a request comes into Nancy you can access it via the dot notation. Or via the class indexer.
var name = parameters.name;
var name = parameters["name"];
This is handy when you're sending query string or form names that have values that cannot be used in dot notation.
var firstName = parameters["first-name"];
The values are also dynamic, so it could be made up of nested objects. This allows you to do stuff like:
var firstName = parameters.contact.firstname;
So if you're passing a JSON payload to the request then you can access the entire structure using dot notation.
However you will probably find most developers using Nancy only ever access Route values or QueryString values using this method.
Get["/products/{id:int}/"] = parameters => {
int id = parameters.id;
};
So back to the original question:
Is there a blog post or any doco: Nope.
Why does it exist: For sugar syntax.
Can I use it for what I want: Yes absolutely!
Can you tell me how to use it: Nope, however it shouldn't be hard. Just look the model binding in Nancy to figure it out. It's not too hard.
Just an edit based on the answer by the OP.
When you access the dot notation, continued dot notation will only work on further dynamic types.
This means using var will cause an exception because of the way var and dynamic are handled by the compiler.
When you do:
var person = parameters.person;
var name = person.name;
parameters is currently dynamic and implements TryGetMember, this internally looks up a dictionary of values and attempts to return the value.
When you define the object as var for the person variable. The compiler assumes that anything after that exists on the object, so it looks for name on the person variable.
Since name does not exist as a member of person it will throw.
To resolve this, the variable must be assigned as dynamic. So the example becomes:
dynamic person = parameters.person;
var name = person.name;
This will work.
So I started working with the DynamicDictionary and it is pretty cool and easy to work with. Only one thing bugs me right now. That is if I nest DynamicDictionaries.
Look at the following example:
private void TestNestedDynamicDictionary()
{
dynamic dictionary = new DynamicDictionary();
dynamic nestedDictionary = new DynamicDictionary();
nestedDictionary.Add("name", "Peter");
dictionary.Add("person", nestedDictionary);
var person = dictionary.person;
var name = person.name;
Console.WriteLine(name);
}
This fails when trying to access person.name with a 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
DynamicDictionaryValue' does not contain a definition for 'name'
If I just do an explicit cast like this it works.
var person = (DynamicDictionary)dictionary.person;
Any input on how I could make it behave as DynamicDictionary right out of the box... apart from checking the DynamicDictionaryValue before it is returned, and do the cast there, which I think is messy.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
object value;
if (!dictionary.TryGetValue(binder.Name, out value))
{
result = new DynamicDictionaryValue(null);
return true;
}
var dictVal = value as DynamicDictionaryValue;
if (null != dictVal && dictVal.Value is DynamicDictionary)
{
result = dictVal.Value;
}
else
{
result = value;
}
return true;
}

WCF Web Service - List<> Return type

List<CertMail> lsRecipetNumber = new List<CertMail>();
CertMail class is in data access layer which returns a List<CertMail>. I need to
convert this to the object of my class and return that
List<CertMailReceiptNumbers> lsReceiptNumbers = new List<CertMailReceiptNumbers>();
CertMailReceipt.lsCMRN = lsReceiptNumbers; //---- > return this.
How do i add all the rows in the CertMail list to CertMailRecieptNumbers and return that from CertMailRecieptNumbers class?
If you only need to map from CertMail to CertMailReceipt and the two types are very similar, you could use an automagic helper like AutoMapper to help you with the mapping.
Basically, AutoMapper will handle much of the boring and error-prone left-right code - assigning one property on the target to a property on the source object.
In your case, if the two types are somewhat similar, you could do something like:
using AutoMapper;
Mapper.CreateMap<CertMail, CertMailReceipt>();
sourceList.ForEach(certMail =>
{
lsReceiptNumbers.Add(Mapper.Map<CertMail, CertMailReceipt>(certMail))
});
or if you prefer:
using AutoMapper;
Mapper.CreateMap<CertMail, CertMailReceipt>();
foreach(certMail cm in sourceList)
{
lsReceiptNumbers.Add(Mapper.Map<CertMail, CertMailReceipt>(cm));
}
This is basically the same idea that NPayette mentioned, just using an half-automatic mapper, instead of having to write the whole mapping process yourself.
And with a bit of luck (and depending on your types of data structures), you might even get the benefit of Automapper being able to even map entire lists from one type to another:
lsReceiptNumbers = Mapper.Map<List<CertMail>,
List<CertMailReceipt>>(sourceList);
Automapper will go through the list of items itself, and apply its mapping to each item, and add those to the resulting output list.
If I understand correctly your need it's a simple mather of mapping from one to another.
Well you need to go throu your CertMail list and then for each of them create a new CertMailReceiptNumbers
Ex.
...
lsReceiptNumber.ForEach(certMail =>
{
lsReceiptNumbers.Add(convertToCertMailReceiptNumber(certMail));
});
return lsReceiptNumber
}
Public CertMailReceiptNumbers convertToCertMailReceiptNumber(CertMail cm)
{
var cmrn = new ertMailReceiptNumber();
cmrn.xxx = cm.xxxx;
...;
return cmrn;
}

Categories