How to use Projections with references? - c#

I have a mapping that has two references to two other mappings.
Firstly, would I create sub-criteria or create aliases?
So I have:
Base.Property1
Base.Property2
Base.Reference1.Property1
Base.Reference1.Property2
Base.Reference2.Property1
Base.Reference2.Property2
I want to project my query to just these 6 properties.
I have managed to use Projections on a query on just one table, but I'm having difficulty when it comes to multiple tables.
would I do something like (for each reference):
criteria.CreateCrtieria(bla)
.SetProjection(Projections.ProjectionList()
.Add(/*Add projections*/))
.SetResultTransformer(Transformers.AliasToBean(type));
Or just create aliases and have projections on the original criteria like so:
criteria.CreateAlias("reference1", "r1").CreateAlias("reference2", "r2")
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("baseProperty1")
.Add(Projections.Property("r1.property1")
.Add(Projections.Property("r2.property2")) /*etc*/
.SetResultTransformer(Transformers.AliasToBean(baseType));
I don't know if the previous two ideas actually work - they don't seem to, but I don't know if that's because I've forgotten something or if they're along totally the wrong lines.
Thanks.

Using the CreateAlias methods on the Criteria API allow you to join across to your referenced objects and allow you to project out the properties.
You assign each referenced type an alias which you then use to access the properties of the referenced objects.
Also please be aware that you need to make sure the names of the properties in the object you are projecting into are an exact match in the projection list.
You can also specify the JoinType on the CreateAlias methods as well should you want to force a InnerJoin instead of a LeftJoin.
var query = session.CreateCriteria<Base>()
.CreateAlias("Base.Reference1","ref1")
.CreateAlias("Base.Reference2","ref2")
.SetProjection(
Projections.ProjectionList()
.Add(Projections.Property("Base.BaseProperty"),"DtoBaseProperty")
.Add(Projections.Property("ref1.property1"),"DtoProperty1")
.Add(Projections.Property("ref2.property2"),"DtoProperty2")
)
.SetResultTransFormer(Transformers.AliasToBean(typeof(ProjectionDto)))
.List<ProjectionDto>();
public class ProjectionDto{
public string DtoBaseProperty;
public string DtoProperty1;
public string DtoProperty2;
}

My solution ended up requiring me to write a new Transformer. I'm not going to paste the code because it's fairly long and at the moment quite hacky. But for anyone interested:
Rather than doing .Add(Projections.Property("r1.property1")
I did .Add(Projections.Property("r1.property1"), "SubType.Property1")
Then in the transformer the alias "SubType.Property1" has a tuple value associated with it. I split the alias up and construct a SubType, and for any aliases associated with it, do the same as what the existing transformer does (assign values to those properties on that type), and then finally set the subtype object as a value to the property on the base type.
It's probably completely against the concept of Projections but it works, and works quite well, considering it was hacked together in a couple of hours.

Related

How can I compare a ClassDeclarationSyntax object against an IdentifierNameSyntax object?

I'm writing a source generator in C#, and I've got 2 objects that I need to compare to see if they relate to the same class, but I can't find a way to do it.
My first object is an instance of ClassDeclarationSyntax. This is coming from my custom ISyntaxContextReceiver to find classes that match specific conditions.
Elsewhere in my generator I have an IdentifierNameSyntax object, which is coming from looking at the types within a TypeOfExpressionSyntax that I find within a different class's list of attributes.
I need to compare the two objects here to see if they are talking about the same thing.
With the IdentifierNameSyntax I can get the type information by using the semantic model:
ITypeSymbol semanticType = semanticModel.GetTypeInfo(targetType).Type;
But I don't know how to compare this ITypeSymbol against ClassDeclarationSyntax either.
Is there a way to do this, or is there a way to get the semantic model type information for a ClassDeclarationSyntax object?
The method you are looking for is GetDeclaredSymbol on semanticModel. As you can see from the documentation, there are huge number of overloads which will allow you to get the associated symbol information for not only classes, but also fields, methods, properties, events, parameters, and so forth. Definitely a method you'll want to keep in your back pocket!

E pluribus unum: merge objects into one

I have a predefined data format, which requires me to have an object like this:
settings:{
settingA:'someValueFromSql',
settingB:'someValueFromAD'
settingC:'someValueFromConfigFile',
settingD:'someValueFromReflection',
settingE:42,
...
}
This settings object is in fact a huge mess of data stitched together from many different sources, but this is how the data is expected by the frontend. I'd like to put the "get/process all data from one source" in a function each, and tape the object together in the end.
So I would have one object
sqlSettings:{
settingA:'someValueFromSql',
settingG:'someOtherValueFromSql',
...
}
returned by function a, and an object
adSettings:{
settingB:'someValueFromAD',
settingV:'someOtherValueFromAD',
...
}
returned by function b, and an object
settings includes adSettings, sqlSettings
where, with at most two simple steps, I can "join together" both objects into a flat third object.
Is this possible with fixed-size objects, without using a generic Dictionary, or am I barking up the wrong tree?
(I'm sure this question was already asked on SO, but I guess I don't find the right words)
It's not possible with a "normal" object, but you can do it with an ExpandoObject and the dynamic keyword. But you need at least .net 4.0
dynamic settings = new ExpandoObject();
//If you try to assign a property that doesn't exist, it is added to the object.
settings.SettingA="sfgd"
Anyway I discourage using this approach. why you don't want to use a IDictionary<string, object> or better a IDictionary<string, MyCustomSettingObject>
--------------------UPDATE---------------------
if the only thing that stops you from using a dictionary is the serialization you can implement the IXmlSerializable Interface and ouput the xml you like:
Proper way to implement IXmlSerializable?
If those partial setting objects have fixed size (meaning fixed number of properties), then you can definitely create a flat object with e.g. only properties to fit all the values in. Then to ease your work, you can try to use Automapper to map the partial objects to the "grouped" object.
http://automapper.codeplex.com/
Otherwise, you will have to stick with the dictionary.

Merging Objects of different types

I have two objects (WS.Customer and EF.Customer). The reason for this is my vendor didn't expose all of the fields in their object (WS.Customer) and I need to insert and update into those fields.
I need to merge WS.Customer -> EF.Customer and later merge EF.Customer -> WS.Customer. EF.Customer will have some extra fields that WS.Customer won't have, but when the field names match - I want the values merged.
I also only want to merge values where the destination field is null, empty, or a default value in case of a Guid.
I know I could use to Linq to query each object and build the other, but is there a less verbose way of doing things? I have some other objects I need to use this approach for and don't feel like spending a weeks typing away.
Thanks
You can use one of the available object-to-object mappers library like AutoMapper or EmitMapper. They will take care of copying the data in both directions and skip fields if properly configured. For example with EmitMapper your code might look like this:
ObjectMapperManager.DefaultInstance
.GetMapper<WS.Customer, EF.Customer>(<your configuration object here>)
.Map(customerSource, customerDestination);
What do you mean by "merged"? I guess you need to "translate" from one instance to another, i.e. copy values when name and type of property matches. Please have a look at the implementation provided in ServiceStack, the extension method of object - TranslateTo method: https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/ReflectionExtensions.cs#L31

Simple way to return anonymous types (to make MVC using LINQ possible)

I'd like to implement MVC while using LINQ (specifically, LINQ-to-entities). The way I would do this is have the Controller generate (or call something which generates) the result-set using LINQ, then return that to the View to display the data. The problem is, if I do:
return (from o in myTable select o);
All the columns are read from the database, even the ones (potentially dozens) I don't want. And - more importantly - I can't do something like this:
return (from o in myTable select new { o.column });
because there is no way to make anonymous types type-safe! I know for sure there is no nice, clean way of doing this in 3.5 (this is not clean...), but what about 4.0? Is there anything planned, or even proposed? Without something like duck-typing-for-LINQ, or type-safe anonymous return values (it seems to me the compiler should certainly be capable of that), it appears to be nearly impossible to cleanly separate the Controller from the View.
Use a view model layer. Your view has to know what it is going to display. I guess its possible to create a view that just formats a multi-dimensional array of data, but that isn't exactly the best reason to go with an MVC solution. You can however populate a view model with an anonymous object for consumption in your view.
Anonymous types are primarily designed to be used within a method. They are not suitable for communication between methods.
If you need to pass a set of data between two functions the best way is to create a new type wrapping the data or use a loser grouping like Tuple<T1,T2> or KeyValuePair<TKey,TValue>
How about this?
I assume that you have an entity class for your table 'myTable' (let's call it 'MyTableEntity'), so why don't you instantiate a new MyTableEntity object and use object initializer to fill only those columns you want?
return (from o in myTable select new MyTableEntity { AColumn = o.column });
This will not translate to a SELECT * as you asked, but you'll still have a way to pass a strongly-typed object to a view.
You have to be careful to just make use of the initialized properties inside the view and that's it.
Does this makes sense for you?
Since no one even attempted to answer my question, I will answer it myself..
It turns out, C# 4.0 supports duck-typing - they call it dynamic typing. However, in using dynamic types to return anonymous types, we lose the benefits of strong types:
Compile-time type-checking
Performance
Intellisense
I've opened a feature request to have strongly-typed anonymous return types here - if you think this would be a useful addition to C# 5, follow the link and let the .Net team know!
On .NET 4.0 Anonymous types can easily be converted to ExpandoObjects and thus all the problems is fixed with the overhead of the conversion itself.
Check out here
You can easily convert anonymous types into dynamic objects, here is the simple implementation of Donymous objects (Dynamic anonymous objects) that can populate from Anonymous object or DataReader.

LINQ to SQL Custom Property query on where clause

I am using LINQ to SQL classes, and have extended one (with a partial class) and added an extra property. I want to query on this property, so:
(from p in db.TableName where p.CustomProperty=="value" select p)
However this doesn't work. I get an error: The member 'TableName.CustomProperty' has no supported translation to SQL. At the moment I have no code in the 'set' section of my Custom Property as I'm unsure how.
So basically, Custom Property which can be queried on with LINQ to SQL, how?
As a follow up: this CustomProperty is NOT a column in the table. It is a separate value, but I need to both fetch it (easy enough) but also query on it!
As you can understand, there can't be any magic, so essentially there will be two queries: first one is a SQL query with database criteria and on its result there should be applied your custom criteria as a second query.
So the workaround you could use is to split two parts explicitly like this:
var dbFetch = (from p in db.TableName where p.RealProperty ==" value" select p).ToArray();
var result = from p in dbFetch where p.CustomProperty == "value" select p;
But of course you'll run into several limitations. For example if you fetching results page-by-page, the second criterion will break paging since it performs additional filtering.
HTH
It's called LINQ to SQL. Just to avoid misunderstandings.
About your problem: have you added that property using the designer? And have you re-created the database after that?
If you did it by hand, make sure you have a private storage field (like _CustomProperty), and your property (CustomProperty) is marked with the ColumnAttribute, e.g.
private string _CustomProperty;
[Column(Storage="_CustomProperty", CanBeNull=true)]
public string CustomProperty
{
get { return _CustomProperty; }
}
Hope this helps.
Aren't you missing an equality sign there? In C#, equality is expressed with double equal signs, as in "a == b", while single equal sign signifies assignment, as in "obj.SomeProp = 5;"
I have implemented a system where you can query manually added properties that represent enumerated wrappers around integer properties from database columns. So I know it's possible, and it looks like you might be wanting to do something similar. The way I did it was not easy, though, and unless you are building a framework that you want to use properly for many cases, you might be better off using the solution suggested by archimed7592. I don't have the code handy at the moment so I can't provide all the details, but briefly my solution works like this. I created a custom LINQ provider, replacing the LINQ-to-SQL provider. I did this by implementing a custom IQueryable interface that returned my LINQ provider instead of that provided by LINQ-to-SQL. Then, in the functions that take expression objects, I pre-processed the expression before returning the result. I replaced all comparisons between enum-type properties and enum values with comparisons between integer properties and integer values, then passed that expression to the normal LINQ-to-SQL implementation in order to return the result. Since expressions are read-only, I had to make a (recursive) function that re-built the entire expression with the customized parts replaced.

Categories