FluentNHibernate: Just another Mapping Question - fluent-nhibernate

Which convention should be used to alter column name of CompositeId().KeyReference(x=>x.Key,/*THIS PART*/) method? I have used all available conventions in FluentNHibernate.Conventions and still haven't found the answer.
Thanks in advance

still not possible now (FNH 1.2), except with some reflection-magic
class CompositeKeyConvention : ICompositeIdentityConvention
{
public void Apply(ICompositeIdentityInstance instance)
{
var columninspector = instance.KeyManyToOnes.First(k => k.Name == "Key").Columns.First();
var columnmapping = (ColumnMapping)columninspector.GetType().GetField("mapping", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic).GetValue(columninspector);
columnmapping.Name = "mycolumnname";
}
}

Related

Get and manipulate data from elasticsearch

I am new to elasticsearch so I will need some help. Unfortunately, I didnt found the answer in other topics here on SO.
I have some .net core application which I inherited and now there is a need to implement some changes.
I already have a method of getting data from elasticsearch, but after getting them, I am not sure how to change it and use it in application.
To be precise, I need to parse first and last name and to remove special characters, specific serbian latin letters like "šđžčć" etc... I already have a method for this parsing written but not sure how to call it...
So, my question is can I and how can I do this?
What I have now is the following:
var result = await _elasticClient.SearchAsync<CachedUserEntity>(
s =>
s.Index(_aliasName)
.Query(q => andQuery));
CachedUserEntity, among others, contains property about FirstName and LastName.
Inside results.Documents, I am getting the data about FirstName and LastName from elasticsearch, but I am not sure how to access it in order to update it via aformentioned NameParser ...
Sorry if the question is too easy, not to say stupid :)
I wont use updateByQuery here, for some reasons. I would scroll on documents (i use matchAll on my exemple, you obviously need to replace it with your query), or, if you dont know how to identify documents to update, only update usefull documents in UpdateManyWithIndex/UpdateManyPartial function.
For performance, we have to update severals documents at once, so we use bulk/updateMany function.
You can use both solution, the classic update, or the second (partial update) with an object containing the targeteds fields.
On server sides, both solutions will have the same cost / performance.
var searchResponse = Client.Search<CachedUserEntity>(s => s
.Query(q => q
MatchAll()
)
.Scroll("10s")
);
while (searchResponse.Documents.Any())
{
List<CachedUserEntity> NewSearchResponse = RemoveChar(searchResponse);
UpdateManyWithIndex<CachedUserEntity>(NewSearchResponse, _aliasName);
searchResponse = Client.Scroll<Project>("2h", searchResponse.ScrollId);
}
public void UpdateManyWithIndex<C>(List<C> obj, string index) where C : class {
var bulkResponse = Client.Bulk(b => b
.Index(index).Refresh(Elasticsearch.Net.Refresh.WaitFor) // explicitly provide index name
.UpdateMany<C>(obj, (bu, d) => bu.Doc(d)));
}
Or, using partial update object
Note: in this case Indix is already set on my client (add .index if needed)
var searchResponse = Client.Search<CachedUserEntity>(s => s
.Query(q => q
MatchAll()
)
.Scroll("2h")
);
while (searchResponse.Documents.Any())
{
List<object> listPocoPartialObj = GetPocoPartialObjList(searchResponse);
UpdateManyPartial(listPocoPartialObj);
searchResponse = Client.Scroll<Project>("2h", searchResponse.ScrollId);
}
private List<object> GetPocoPartialObjList(List<CachedUserEntity> cachedList) {
List<object> listPoco = new List<object>();
//note if you dont have cachedList.Id, take a look at result.source, comments if needed
foreach (var eltCached in cachedList) {
listPoco.Add( new object() { Id = cachedList.Id, FirstName = YOURFIELDWITHOUTSPECIALCHAR, LastName = YOURSECONDFIELDWITHOUTSPECIALCHAR});
}
return listPoco;
}
public bool UpdateManyPartial(List<object> partialObj)
{
var bulkResponse = Client.Bulk(b => b
.Refresh(Elasticsearch.Net.Refresh.WaitFor)
.UpdateMany(partialObj, (bu, d) => bu.Doc(d))
);
if (!bulkResponse.IsValid)
{
GetErrorMsgs(bulkResponse);
}
return (bulkResponse?.IsValid == true);
}

Error C1061 "... does not contain a definition for 'TextBox_TextChanged' ......." update SQL Server database with Entity Framework

I have a database table Doctor which contains columns code_doctor (varchar), name (varchar), gender (varchar), salary (int). I want to implement CRUD in this database, using Entity Framework. But, there's something wrong when trying to update data.
public partial class UpdatePage : Window
{
DB_Rumah_Sakit_2697Entities _db = new DB_Rumah_Sakit_2697Entities();
string code;
public UpdatePage(string codedoc)
{
InitializeComponent();
code = codedoc;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Dokter updateDoctor = (from m in _db.Doctors where m.kd_doctor == kode select m).Single();
updateDoctor.code_doctor = textboxkode.Text;
updateDoctor.name = textboxnama.Text;
updateDoctor.gender = gendercombobox.Text;
updateDoctor.salary= int.Parse(textboxgaji.Text);
_db.SaveChanges();
MainWindow.datagrid.ItemsSource = _db.Dokters.ToList();
this.Hide();
}
}
I think the issue may be here:
from m in _db.Doctors where m.kd_doctor == kode
I don't see kode declared anywhere. Is that supposed to be code?
I would probably avoid mixing the linqQL with the fluent functions and just use Fluent:
Dokter updateDoctor = _db.Doctors.Single(x => x.kd_doctor == code);
Other than that nothing really stands out. From the exception it would look like you are possibly missing a .Text or such from one of your properties, though I'd suspect that would be in a query expression.
Is that the exact code you have in your application? On which line does the exception occur, on the .Single() or _db.SaveChanges()?

Ignite SqlQuery for complex java objects

In my cache I have a complex java object as below -
class Person{
private Department d;
....
}
class Department {
private Department code;
....
}
I am using below SQLQuery to read it -
SqlQuery<Short, BinaryObject> query = new SqlQuery<>(Person.class, "d.code = ?");
String args="101"; // department code
QueryCursor<Cache.Entry<Short, BinaryObject>> resultSet = personCache.query(query.setArgs(args))
I am getting below error -
Caused by: class org.apache.ignite.internal.processors.query.IgniteSQLException: Failed to parse query: SELECT "PERSON_CACHE"."PERSONENTITY"._KEY, "TPERSON_CACHE"."PERSONENTITY"._VAL FROM "PERSON_CACHE"."PERSONENTITY" WHERE id.code = ?
Am I doing anything wrong here ?
You can access nested fields, but only if they were configured with QuerySqlField annotation in advance:
class Person{
private Department d;
...
}
class Department {
#QuerySqlField
private Department code;
....
}
SqlQuery<Short, BinaryObject> query = new SqlQuery<>(Person.class, "code = ?");
Destructuring is not supported by Ignite SQL and there are no solid plans to implement it.
This means you can't peek into fields that are rich objects, maps, lists, etc. You should introduce a departmentId numeric field here.
Theoretically you could also try putting #QuerySqlField annotation on Department's field code, and then access it as CODE = ?. Your mileage may vary. I for one would like to hear about the result of such experiment.
I resolved it by using predicate.
IgniteBiPredicate<Long, BinaryObject> predicate = new IgniteBiPredicate<Long, BinaryObject>() {
#Override
public boolean apply(Long e1, BinaryObject e2) {
Person p= e2.deserialize();
short s = (short) args[0];
return p.getId().getCode == s;
}
};

asp.net mvc Type.GetMethod when two action with same name, but get and post

in asp.net mvc 4, I write a custom Exception handler, working as a Attribute named HandleCustomError.
In this handler, I should know which action the current request for, then I can know what kind of return type for this action. I will return different data for "return type view() and json".
But, now I have two action with the same name, but one is for "Get", other is for "Post".The method "GetMethod" return an error: " System.Reflection.AmbiguousMatchException "
public class HandleCustomError : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
{
//base.OnException(filterContext);
if (filterContext.ExceptionHandled)
{
return;
}
else
{
//Determine the return type of the action
string actionName = filterContext.RouteData.Values["action"].ToString();
Type controllerType = filterContext.Controller.GetType();
var method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var returnType = method.ReturnType;
}
....(Omitted)
I also came across this issue that below line was giving Ambigeous issue
controllerType.GetMethod(actionName, BindingFlags.IgnoreCase |
BindingFlags.Public | BindingFlags.Instance);
Reason was that controller has two method with same name one is
[HTTPGET]
and other iis
[HTTPPOST]
.
For to get exact method I use GetMethods and LINQ.
Note: In controller writting [HTTPGet]**on action is not compulsory for get method i.e. on action if HTTpGet is not written the by default .net will consider it as **[HttpGet]. But for post action it is compulsory.
Will use this property for finding the correct method.
Steps
1. Find Type of request
2. Find the action using reflection
Finding Request type:
var actionName =
filterContext.RouteData.Values["action"].ToString();
Type typeOfRequest = filterContext.HttpContext.Request.RequestType.ToLower()
=="get"?typeof(HttpGetAttribute):typeof(HttpPostAttribute);
Finding method:
var cntMethods = controllerType.GetMethods()
.Where(m =>
m.Name == actionName &&
( ( typeOfRequest == typeof(HttpPostAttribute) &&
m.CustomAttributes.Where(a => a.AttributeType == typeOfRequest).Count()>0
)
||
( typeOfRequest == typeof(HttpGetAttribute) &&
m.CustomAttributes.Where(a => a.AttributeType == typeof(HttpPostAttribute)).Count() == 0
)
)
);
MethodInfo actionMethodInfo = actionMethodInfo = cntMethods != null && cntMethods.Count() == 1 ? cntMethods.ElementAt(0):null;
Reference : https://techatfingers.wordpress.com/2016/06/14/session-state-on-action/
As you have mentioned that you have two action with the same name, but one is for "Get", other is for "Post" , You could try out the [HttpGet] to the first action and [HttpPost] to the section action or you can try something like this if your action serves requests from multiple verbs
[HttpGet, HttpPost] or [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
For Example ,
if your function name is GetMethod then try like this
[HttpGet]
Public ActionResult GetMethod()
{
//do something ...
}
[HttpPost]
Public ActionResult GetMethod()
{
//do something ...
}
One approach to solve this issue is to use the GetMethods() method on the System.Type object to return a list of methods on the System.Type object. Use a LINQ query to filter the method list to just those methods that match a specific action name.
Add this approach by replacing the following in your code:
var method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
with the following if condition that checks if multiple methods are found that match the variable actionName from your code. Define a string variable that identifies the action type (i.e. "HttpGet" or "HttpPost") and compare it to the attributes of each method in the filtered list.
System.Reflection.MethodInfo[] matchedMethods = controllerType.GetMethods(
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
.Where(m => m.Name == actionName).ToArray<System.Reflection.MethodInfo>();
if (matchedMethods.Length > 1)
{
string attributeTypeString = "HttpGet"; // Change this to "HttpPut" or the text of any custom attribute filter
foreach (System.Reflection.MethodInfo methodInfo in matchedMethods)
{
if (methodInfo.CustomAttributes.Count() == 0) { continue; }
// An alternative below is to explicitly check against a defined attribute type (e.g. `ca.AttributeType == ...`).
if (methodInfo.CustomAttributes.FirstOrDefault(ca => ca.ToString().IndexOf(attributeTypeString) == 0) !=null)
{
method = methodInfo;
break; // Break out of the 'foreach' loop since a match was found
}
}
}
else
{
method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
}
Code notes
I used strongly-typed variable declarations (versus 'var') so it's easier to follow what the code is doing.
Add using System.Reflection; and using System.Linq at the top of the class file. I listed the full assembly declaration of a variable/type/flag in the code above so that again it's easier to follow (at least for me) in this answer.
The first line of code in the above solution can be broken into separate lines to make it easier to follow:
System.Reflection.MethodInfo[] allMethods = controllerType.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
System.Reflection.MethodInfo[] matchedMethods = allMethods.Where(m => m.Name == actionName).ToArray<System.Reflection.MethodInfo>();
Note the if condition within the foreach loop.
if (methodInfo.CustomAttributes.FirstOrDefault(ca => ca.ToString().IndexOf(attributeTypeString) == 0) !=null)
The if condition doesn't have to convert the custom attribute to a string. An alternative is to explicitly check against a defined attribute type (e.g. ca.AttributeType == ...). If the condition does check against the text of an attribute name then ensure the string comparison method (e.g. IndexOf() used here) satisfies the conditions of your application. For example, I used IndexOf() > -1 to determine if the text of variable attributeTypeString is listed anywhere in a custom attribute because I assumed that there should not be another custom attribute that contains the text 'HttpGet'.

RavenDB: Indexing documents from multiple collections

I have several document collections that occasionally need to be pulled together into a single index for reporting purposes.
This FAQ provides a solution for writing such an index in Raven Studio: http://ravendb.net/faq/indexing-across-entities
While I understand I won't get full compile-time checking, I'm trying to avoid completely unchecked code like this:
public class Assets_ById : AbstractIndexCreationTask
{
public override IndexDefinition CreateIndexDefinition()
{
return new IndexDefinition
{
Map = #"from doc in docs
where doc[""#metadata""][""Raven-Entity-Name""] == ""Cars"" ||
doc[""#metadata""][""Raven-Entity-Name""] == ""Trains"" ||
doc[""#metadata""][""Raven-Entity-Name""] == ""Boats"" ||
doc[""#metadata""][""Raven-Entity-Name""] == ""Planes""
select new
{
Cost = doc.Cost,
Id = doc.Id,
Name = doc.Name,
Type = doc.Type,
};"
}
}
}
Is there something similar to the generic AbstractIndexCreationTask<T> that will allow me to define a heterogeneous index with lambda expressions?
You can use WhereEntityIs(names), like this:
from doc in docs.WhereEntityIs<Vehicle>("Cars", "Trains", "Boats", "Planes")
select new
{
doc.Cost,
doc.Name,
doc.Type
}
Take a look here: https://groups.google.com/forum/#!topic/ravendb/9wvRY0OiGBs
It's basically the same question and the short answer is:
"right now there isn't a better option, but there will be in the future"