I am working with OData V3, and i came across this line:
var people = await client.For<People>().FindEntriesAsync();
In order for this to work, I need to define the People class, which has a bunch of set/get, which represent the fields I want.
Is there a simple and convenient way to avoid hard coding the structure classes? I want to be able to issue that command without having to define a specific "People" class. I would much rather have my results be in dictionary form, were the key's would be the column name, and the value would be the value in that column for the specific object.
Simple.OData.Client supports untyped scenarios, in which the CLR class is unnecessary.
For example:
var people = await client.For("People").FindEntriesAsync();
Then, people is a dictionary instance that you can use IDictionary<string, object> to refer. Thanks.
I don't think there is a way to avoid define a class like People, but if you really want to do this, you can try un-typed feature in OData.
Simple.OData.Client supports typed, untyped and dynamic scenario. So you can rewrite your query like this:
var x = ODataDynamic.Expression;
var people = await client.For(x.People).FindEntriesAsync();
here is another example:
var person = await client
.For(x.People)
.Filter(x.FirstName == "John")
.Select(x.LastName)
.FindEntryAsync();
Related
I have been using Dapper.net for a while now and its a very good ORM mapper which works great with .Net dynamic types.
But I noticed that when Dapper retrieves data from a database it returns as DapperRow type.
Is there are any way that I can return it in any other type Like System.Dynamic.ExpandoObject?
Sure!
As per dapper documentation use the query method and get your dymanics:
dynamic account = conn.Query<dynamic>(#"
SELECT Name, Address, Country
FROM Account
WHERE Id = #Id", new { Id = Id }).FirstOrDefault();
Console.WriteLine(account.Name);
Console.WriteLine(account.Address);
Console.WriteLine(account.Country);
As you can see you get a dynamic object and you can access its properties as long as they are well defined in the query statement.
If you omit .FirstOrDefault() you get an IEnumerable<dynamic> which you can do whatever you want with it.
The DapperRow object is designed to share a lot of state between rows. For example, if you fetch 40 rows, the column names etc are only stored once. If we used ExpandoObject, this would need to be configured per row. Hence, the use of DapperRow as the behind-the-scenes implementation detail is a deliberate efficiency thing.
Note that the object returned from the dynamic APIs can also be cast as IDictionary<string,object>.
I would, however, be open to supporting other types that support this dictionary usage - of which ExpandoObject is one. So yes, it could be changed such that:
var rows = conn.Query<ExpandoObject>(...);
works. It simply requires code to support it, and that code does not currently exist. So "no, but perhaps in a future build".
Note also that you don't need to use DapperRow at all... The more expected scenario is to use the generic API to materialize your own types.
I have this problem and I solved by this way!
The Query() function returns a collection of dynamics which underneath are actually Dapper.SqlMapper.DapperRow object types. The Dapper.SqlMapper.DapperRow is private. I needed to dynamically add properties to the Dapper.SqlMapper.DapperRow objects but that doesn't appear to work. As a result I wanted to convert the Dapper.SqlMapper.DapperRow into an ExpandoObject.
I was able to build this generic helper method like below.
public class DapperHelpers
{
public static dynamic ToExpandoObject(object value)
{
IDictionary<string, object> dapperRowProperties = value as IDictionary<string, object>;
IDictionary<string, object> expando = new ExpandoObject();
foreach (KeyValuePair<string, object> property in dapperRowProperties)
expando.Add(property.Key, property.Value);
return expando as ExpandoObject;
}
}
Then you can use that like this:
IEnumerable<ExpandoObject> result =
db.SqlConn.Query(sqlScript)
.Select(x=> (ExpandoObject)ToExpandoObject(x));
reference: dapper-dot-net issues 166
I am populating my viewmodels from linq queries. I have a method to retrieve a list of plans that looks something like this
public static IEnumerable<PlanViewModel> GetPlans()
{
using (var context = new RepEntities())
{
var query = (from p in context.Plans.Include("StatusCommon")
join r in context.RealEstateDetails on p.ReId equals r.ReId
select new PlanViewModel
{
PlanName = p.PlanName,
...
LastUpdated = p.LastUpdated,
});
return query.ToList();
}
}
Where you see the ellipses are about 30 other properties. Now I want to build a method to return a single Plan. The method would be virtually the same except that it will contain a where clause to specify a plan Id. I would like to refactor this code so that I am not duplicating the mapping of the Model to the ViewModel. However, I'm not finding a way that allows me to do this. Can anyone offer any suggestions as to how to properly code this so that here isn't so much duplication?
Thanks in advance!
Either use reflection to populate the fields, or go with a library like AutoMapper. I'd definitely recommend using AutoMapper though, it will keep your code a lot cleaner.
Another possibility is using implicit or explicit converters.
It pretty much depends where you want to have the code:
Utility class (reflection)
Models/ViewModels (implicit or explicit)
Anywere (AutoMapper)
This won't make a lot of sense so apologies in advance, I'm not a C# developer but have been given some code to look at.
I need to pass a model object in to a function, however I looping through and so will need to build the name dynamically. So lets assume I would normally reference it like so.
model.employee.title
model.employee.forename
How can I reference it using a string for the last part.
I'm using a foreach to loop through the various parts which is fine, but I then need to pass the object in to a function call. I have the name of the last part as a literal string ("title","forname") but I'm not sure how I pass that in.
So effectively what I need is to use something like
model.employee."title"
or
model.employee.varContainingTheName
I know these won't work, but have no idea how to proceed.
Basically, if you have a string of the member name, you're talking about reflection. The reflection API differs between fields and properties, so you'd need to know which it is, for example (where obj is model.employee, and name is the name of the member you want to access):
object value = obj.GetType().GetField(name).GetValue(obj);
vs:
object value = obj.GetType().GetProperty(name).GetValue(obj, null);
Alternatively, use an API like FastMember (which incidentally is much faster than raw reflection - it uses lots of voodoo):
var wrapper = ObjectAccessor.Create(obj);
object value = wrapper[name];
If you develop the model.employee class and use it like that, you should consider using dictionary for fileds.
class employee
{
public Dictionary<string, object> properties = new Dictionary<string,object>();
public employee()
{
properties.Add("time", DateTime.Now);
properties.Add("name", "Bill Gates");
}
}
and then use it like this:
Employee employee = new Employee();
employee.properties["time"];
this code will be faster and easier to read.
I'm trying to implement a class in a Silverlight 4 RIA Services application that manages different ObservableCollections that are used for data binding. These ObservableCollections need to be identified by a string name and an integer classID, which I have implemented by nesting Dictionary objects in a Dictionary> object. The problem is, if I have explicit Entity types (which I do), this structure does not seem to work. The problem seems to occur when I am trying to put an ObservableCollection into an ObservableCollection (my guess as to how a generic entity list would be implemented).
For example:
this.rawData = new Dictionary<int, ObservableCollection<DataRaw>>();
this.constData = new Dictionary<int, ObservableCollection<SystemConstant>>();
this.masterData = new Dictionary<string, Dictionary<int, ObservableCollection<Entity>>>();
masterData.Add("test", rawData); <--- ERROR OCCURS HERE, 'best overloaded method has invalid arguments'
Note that I have tried using 'Object' instead of 'Entity' in the instantiation of masterData, but that did not solve the problem (it was admittedly a feeble attempt).
Thanks in advance for your insights. If there is a much better pattern I could be implementing here, I am open to being flexible. I mainly want to avoid having to code a bunch of Entity-type specific logic to manage the updating of this class. It seems like this should be generalizable.
Alex
For this to work you will have to declare RawData using the parent type, like this:
this.rawData = new Dictionary<int, ObservableCollection<Entity>>();
Even if this dictionary will only hold instances of DataRaw, and even if DataRaw is derived from Entity, it is not possible to make an implicit conversion between ObservableCollection<DataRaw> and ObservableCollection<Entity>. For a moment I hesitated on whether C# would be able to solve this using variance, but after a quick proof of concept it was clear it cannot:
var dataRaw = new DataRaw();
Entity testEntity = dataRaw;
var entityObservable = new ObservableCollection<Entity>();
entityObservable.Add(dataRaw); // This is OK
var dataRawObservable = new ObservableCollection<DataRaw>();
dataRawObservable.Add(dataRaw); // This is fine too.
entityObservable = dataRawObservable; // This is not valid
var metaDictionary = new Dictionary<Int32, ObservableCollection<Entity>>();
metaDictionary.Add(1, dataRawObservable); // This isn't valid either.
metaDictionary.Add(2, entityObservable); // This is valid.
I'd like to know the best way of converting a list of domain object I retrieve into custom ViewModels in the controller
e.g.
IList<Balls> _balls = _ballsService.GetBalls(searchCriteria);
into
IList<BallViewModels> _balls = _ballsService.GetBalls(searchCriteria);
it doesn't have to be exactly as I've outlined above i.e. it doesn't have to be an IList and if not accessing the service directly and instead go thru some other layer that converts the objects to viewmodels then that is ok too.
thanks
For simple objects you could just use Linq:
IList<BallViewModel> _balls = _ballsService.GetBalls(searchCriteria)
.Select(b => new BallsViewModel
{
ID = b.ID,
Name = b.Name,
// etc
})
.ToList();
That can get pretty repetitive though, so you may want to give your BallViewModel class a constructor that accepts a Ball and does the work for you.
Another approach is to use a library like AutoMapper to copy the properties (even the nested ones) from your domain object to your view model.
Probably a bit of Linq, something along the lines of
var ballQuery = from ball in _ballsService.GetBalls(searchCriteria)
select new BallViewModels
{
Diameter = ball.Diameter,
color = ball.Color,
...
}
IList<BallViewModels> _balls = ballQuery.ToList();
Either that or the question is more complicated than I think...
I use AutoMapper to do this all the time. It's really flexible and has worked for me without any troubles so far.
First you set up a map like during your app's initialization:
Mapper.CreateMapping<Balls, BallViewModel>();
And whenever you need to map the objects, you would do this:
Mapper.Map<IList<Balls>, IList<BallViewModel>>(_ballsService.GetBalls());
Like I said, it's very flexible and you can modify how the mapping happens for each property using a fluent API.