I'm working on a Silverlight Project with all the features and limitations that entails. This is an update to a previous product. The intent, in order to be quick to market, is to maintain as much of the back-end (webservices, database, etc..) as at all possible. Our mandate it to only touch the back-end if there is no other way. We'll primarily be focused on re-writing the front-end. There's an important industry conference soon where we will want to demo the early look of the product. There may be time prior to the official release to do some re-work, but the back-end may need to wait until V2.
OK, so what I'm trying to do is use the MVVM pattern with data binding for the front-end for which I'm responsible (MVVM pattern is dictated from above). I have a pre-existig web service that serves up some XML. A sample of that XML looks like is below:
<CODEBOOKINDEX>
<ME Words="1" Score="25" Highscore="1">Main Entry Item
<NM>attack</NM>
<NM>cardiac</NM>
<NM>chest</NM>
<NM>effort</NM>
<NM>heart</NM>
<NM>pectoris</NM>
<NM>syndrome</NM>
<NM>vasomotor</NM>
<IE>413.9</IE>
<M1 Words="1" Score="25">An M1 Item (Same as ME, just first level Child)
<IE>557.1</IE>
</M1>
<M1 Words="1" Score="25">Another M1 Item
<IE>443.9</IE>
<M2 Words="1" Score="25">An M2 Item (again same as ME, just a child of an M1 item)
<CF>Arteriosclerosis,extremities</CF>
<IE>440.20</IE>
</M2>
</M1>
</ME></CODEBOOKINDEX>
So, my question, since I want to bind this to a UI using the MVVM pattern, it seems to me that I need to translate this into a custom object. As you can see there are a number of "Entry" items, MainEntry (ME) and Subentries (M1 or M2 in this example), these will all contain certain other nodes (they will all have an IE node, for example), they MAY contain 0 or more other node types (for example they MAY or may not contain one or more NM nodes, or they MAY contain one CF node or not). Whihc means (at least to me) that I can't really bind directly to XML because:
It violates the MVVM pattern (I could probably justify this for the demo, but would have to refactor later).
I can't really bind a UI element to an XML node that MAY not be there for a given item.
In some cases Ihave to translate a collection (a bunch of NM items, for example) into a formated strig for display purposes, which I don't THINK is a trivial thing.
So, I'm trying to understand the best way to translate this XML into a bindable object, which in my mind means transforming this XML into an object for the model and then overlaying a view-model on that model.
Can this be done easily with LINQ to XML queries, or am I really moving into the realm of an ORM such as NHibernate or Entity Framework (no holy wars about WHICH ORM please)?
I've only just established what controls I will be using for UI and I need to demonstrate to my manager rather quickly HOW I'm going to handle the translation.
So, the real questions:
Do I NEED an ORM? I'm not against using them, but I want to keep the size of the XAP file small and want to limit the amount of new tech I (and my teammates) need to learn in a single pass.
If I do need one, can I keep the file size down and can I ramp up quickly with either EF or NHibernatge and have a model to show very soon? I'm talking like a week here to have SOMETHING that will take output from the webservice and turn it into an object, even if the map isn't perfect initially, I need to demonstrate some progress.
Is there another option alltogether that I'm not considering that might be easier, limit the need to modify existing code (i.e. the webservice) and product usable results?
Do I NEED an ORM?
No. You aren't mapping to a relational source, so an object relational mapper won't help.
Get it done with Linq to Xml.
public CustomClass TranslateME(XElement source)
{
CustomClass result = new CustomClass();
result.Words = (int) source.Attribute("Words");
result.Score = (int) source.Attribute("Score");
XAttribute highScore = source.Attribute("HighScore");
result.HighScore = (highScore == null) ? 0 : (int) highScore;
result.NMs = source
.Elements("NM")
.Select(x => x.Value)
.ToList();
result.IE = source
.Element("IE").Value;
result.SubEntries = source
.Elements("M1")
.Select(x => TranslateM1(x))
.ToList();
return result;
}
Related
I have a quite big dilemma nowadays about general viewmodel design concepts. I mean general, like it's not exactly bound to a given language or environment: I had same dilemma when I wrote viewmodels for Winforms, WPF or KnockoutJS.
As a simplified use case, consider that I have a view where I have to select a country and a city from two select boxes. Both are represented in the database with a unique ID, a Name, and some other relevant information like - let's say - Population. Now imagine that I have to present a textual form of the currently selected data in for example the view's heading like "You've selected London, England". Now here is my two alternatives for creating a viewmodel, I will try to enumerate the pros/contras which I'm already thinking of below each version. The code is written in kind of pseudo way to be as generic as possible.
class RegionModel {
ID: number;
Name: string;
Population: number;
}
Version 1: Storing the selected object.
class MainView {
SelectedCountry: RegionModel;
SelectedCity: RegionModel;
SelectionInfo: string; // computed, should return the "You've selected ...." caption
Countries: List<RegionModel>; // datasource for country select
Cities: List<RegionModel> // datasource for city select
}
Pros:
Straightforward and easy to understand due to that the selected
item's type is the same as the selectable items' type.
Easy to compute such infos like "You've selected ..." because all the
members of the currently selected item are present directly.
Cons:
It holds more information than usually a consumer API needs. Usually
it needs only the ID.
If it's used in a client-side app, the whole selected object will be
returned to the server, consuming bandwidth.
If the consumer API needs only ID's (like in most cases), I have to
solve some kind of conversion before I pass it. In a web app probably
during serialization to JSON for example.
Version 2: Storing only the ID's of the selected items
class MainView {
SelectedCountryID: number;
SelectedCityID: number;
SelectionInfo: string; // computed, should return the "You've selected ...." caption
Countries: List<RegionModel>; // datasource for country select
Cities: List<RegionModel> // datasource for city select
}
Pros:
It's efficient in the way that it contains only the information which
is most likely needed by consumer APIs.
No additional conversion is needed, and efficiently can be passed
nearly "as is" to a server-side or other API.
Cons:
Not so straightforward and readable (in my opinion).
What about computing the info string? That's now much harder, I need
to grab the needed members from the selection source lists with a
search by the given ID, so it depends heavily on the consistency of
those lists (I mean the item must be present there).
I hope it won't be closed quickly as unconstructive. Any kind of advices, thoughts or experiences will be appreciated. Also, if the answer is "it depends", please try to give my some points where and when to use which.
UPDATE
I think my question was a bit unclear. I know about decoupling viewmodel from database entities, here I never mentioned database entities. I mentioned an "abstract consumer API". In a concrete scenario: if the API needs the selected items' Names, and my API needs only the IDs, which alternative should I choose, and where should do the conversion?
For example my server expects a data format like this (JSON):
{
"SelectedCountryID": 2,
"SelectedCityID": 5
}
and nothing else. How could I handle it in an elegant way? I would like to avoid repeating myself by doing a manual conversion.
Depending on how your datasources are implemented, it may make not difference: if you are retrieving the list of countries and cities, you can either store a reference to the selected value, to one of its fields or its index in the list.
Disregarding that, you should decouple your view model entities from your database entities and put into your view model ones only those fields required by the views. This way, your information traffic is minimized and your code is less affected by changes in the database.
EDIT following OP's update:
Talking about interacting with an API instead of a database, I think you can apply the same ideas, just replacing "database entities" by "service layer entities" (for instance, the JSON coming in/out your server). Take the returned data that into your view model objects, holding those attributes that you need. Obviously you also may need to store an id as you stated, when you'll need to refer to the same entity later on.
From a theoretical point of view, you should not include any other fields not consumed by the view, but you could do so depending on your requirements. For instance, in cases when you'll need to pass those fields back to the service layer and you don't want to query again by id to retrieve the service entity. However there are other alternatives to this (for example, some kind of cache), the exact balance depends on your requirements.
Base on MVVM pattern your viewModel should be an object with all properties which you need to display in view. ViewModel should be only used to be strictly binded to the view. Anyway your example it's not very good in my opinion. You shouldn't think about viewModel in case of storing something, please think more about presenting data.
Please remember that before you have data in database you have to insert it. So if you have some form with First Name and Last Name, user at first must fill this form and data must be insert into database, without it you don't have any ID.
To summarize in my opinion viewModel should have properties which you have to present to the end-user.
I am in the process of prototyping an implementation of a rules engine to help us with our ordering portals. For example giving discounts on items or requiring approval if certain items are ordered. We would also like to be able to add rules for dollar amounts, user hierarchy positions, and be apply it one client or more.
I feel that WWF is a good answer to this need.
All of that said however I am having a little difficulty figuring out how best to set up some of the more complex rules. I have a "condition" that I feel is best described in a LINQ query, like so:
var y = from ol in currentOrder.OrderLines where ol.ItemCode == "MYITEMCODE" select ol;
I am not against using a different framework for a rules engine or adding additional properties/methods to our objects (ex: OrderHasItem(ItemCode), etc) to make these rules more simplified but I would like to avoid having to do that. It feels self-defeating in that it forces us down the road of potentially requiring code changes for new rules.
Yes, you can use Linq queries with Workflow. In WF what you are referring to as a rule is an expression that is evaluated at runtime. Your query is selecting a subset of the orderliness based on a criteria.
For example, if I have a collection of names and I want to see only names that begin with 'R'. I could write the following code.
private static void ShowQueryWithCode(IEnumerable<string> names)
{
Console.WriteLine("LINQ Query in Code - show names that start with 'R'");
// Assuming there are no null entries in the names collection
var query = from name in names where name.StartsWith("R") select name;
// This is the same thing as
// var query = names.Where(name => name.StartsWith("R"));
foreach (var name in query)
{
Console.WriteLine(name);
}
Console.WriteLine();
}
To do the same with Workflow
Step 1: Create a Workflow with an In Argument of type IEnumerable
Here you can see that I've added the in argument
Step 2: Add a Variable for the query of type IEnumerable
Before you can add a variable you need to include an activity which has variables. In this workflow I've added a sequence.
Step 3: Assign the query the LINQ expression you want to use
You can use a method chain or query syntax.
Step 4: Iterate over the collection
In the completed workflow I used a ForEach activity to iterate the list of names and write them to the console.
This example uses C# in .NET 4.5 but the same technique can be used with Visual Basic.
You can download the sample code here
WF is a workflow engine. It's used to run factories and banks. The rule engine is just a small part of it. To make sense, any normal WF project requires a dedicated team of professionals to build it. Seems like an overkill for your specific purpose. You are very likely to bury yourself and your project in a typical fight between requirements and real skills of your team.
The use of any available .NET engine would be more justified in your situation. Keep in mind that building a custom rule engine is not an easy tasks, no matter how simple it seems from the beginning. Setting property values of a class (typically called a "fact" or "source" object) or executing actions (invoking class' methods) is what rules engines do best. And it seems that it's exactly what you need. Check out some available .NET engines. They are inexpensive, if not free, and reliable.
For a utility I'm working on, the client would like to be able to generate graphic reports on the data that has been collected. I can already generate a couple canned graphs (using ZedGraph, which is a very nice library); however, the utility would be much more flexible if the graphs were more programmable or configurable by the end-user.
TLDR version
I want users to be able to use something like SQL to safely extract and select data from a List of objects that I provide and can describe. What free tools or libraries will help me accomplish this?
Full version
I've given thought to using IronPython, IronRuby, and LuaInterface, but frankly they're all a bit overpowered for what I want to do. My classes are fairly simple, along the lines of:
class Person:
string Name;
int HeightInCm;
DateTime BirthDate;
Weight[] WeighIns;
class Weight:
int WeightInKg;
DateTime Date;
Person Owner;
(exact classes have been changed to protect the innocent).
To come up with the data for the graph, the user will choose whether it's a bar graph, scatter plot, etc., and then to actually obtain the data, I would like to obtain some kind of List from the user simply entering something SQL-ish along the lines of
SELECT Name, AVG(WeighIns) FROM People
SELECT WeightInKg, Owner.HeightInCm FROM Weights
And as a bonus, it would be nice if you could actually do operations as well:
SELECT WeightInKg, (Date - Owner.BirthDate) AS Age FROM Weights
The DSL doesn't have to be compliant SQL in any way; it doesn't even have to resemble SQL, but I can't think of a more efficient descriptive language for the task.
I'm fine filling in blanks; I don't expect a library to do everything for me. What I would expect to exist (but haven't been able to find in any way, shape, or form) is something like Fluent NHibernate (which I am already using in the project) where I can declare a mapping, something like
var personRequest = Request<Person>();
personRequest.Item("Name", (p => p.Name));
personRequest.Item("HeightInCm", (p => p.HeightInCm));
personRequest.Item("HeightInInches", (p => p.HeightInCm * CM_TO_INCHES));
// ...
var weightRequest = Request<Weight>();
weightRequest.Item("Owner", (w => w.Owner), personRequest); // Indicate a chain to personRequest
// ...
var people = Table<Person>("People", GetPeopleFromDatabase());
var weights = Table<Weight>("Weights", GetWeightsFromDatabase());
// ...
TryRunQuery(userInputQuery);
LINQ is so close to what I want to do, but AFAIK there's no way to sandbox it. I don't want to expose any unnecessary functionality to the end user; meaning I don't want the user to be able to send in and process:
from p in people select (p => { System.IO.File.Delete("C:\\something\\important"); return p.Name })
So does anyone know of any free .NET libraries that allow something like what I've described above? Or is there some way to sandbox LINQ? cs-script is close too, but it doesn't seem to offer sandboxing yet either. I'd be hesitant to expose the NHibernate interface either, as the user should have a read-only view of the data at this point in the usage.
I'm using C# 3.5, and pure .NET solutions would be preferred.
The bottom line is that I'm really trying to avoid writing my own parser for a subset of SQL that would only apply to this single project.
There is a way to sandbox LINQ or even C#: A sandboxed appdomain. I would recommend you look into accepting and compiling LINQ in a locked-down domain.
Regarding NHibernate, perhaps you can pass the objects into the domain without exposing NHibernate at all (I don't know how NHibernate works). If this is not possible, perhaps the connection to the database used within the sandbox can be logged in as a user who is granted only SELECT permissions.
Maybe the expressions will come handy for You.
You could provide simple entry places for:
a) what to select - user is expected to enter an expression only _ probably member and arithmetic expressions - those are subclasses of the expression class
b) how to filter the things = again only expressions are expected
c) ordering
d) joining?
Expressions don't let You do File.Delete because You operate only on precise domain objects (which probably don't have this functionality). The only thing You have to check is whether the parameters of the said expressions are of Your domain types. and Return types of said expressions are of domain types (or generic types in case of IEnumerable<> or IQuerable<>
this might prove helpful
I.E. expressions don't let You write multi-line statements.
Then You build your method chain in code
and voila.
There comes the data
I ended up using a little bit of a different approach. Instead of letting users pick arbitrary fields and make arbitrary graphs, I'm still presenting canned graphs, but I'm using Flee to let the user filter out exactly what data is used in the source of the graph. This works out nicely, because I ended up making a set of mappings from variable names to "accessors", and then using those mappings to inject variables into the user-entered filters. It ended up something like:
List<Mapping<Person>> mappings;
// ...
mappings.Add(new Mapping("Weight", p => p.Weight, "The person's weight (in pounds)"));
// ...
foreach (var m in mappings)
{
context.Variables[m.Name] = m.Accessor(p);
}
// ...
And you can even give an expression context an "owner" (think Ruby's instance_eval, where the context is executed with score of the specified object as this); then the user can even enter a filter like Weight > InputNum("The minimum weight to see"), and then they will be prompted thusly when the filter is executed, because I've defined a method InputNum in the owning class.
I feel like it was a good balance between effort involved and end result. I would recommend Flee to anyone who has a need to parse simple statements, especially if you need to extend those statements with your own variables and functions as well.
I am building a search application that has indexed several different data sources. When a query is performed against the search engine index, each search result specifies which data source it came from. I have built a factory pattern that I used to display a different template for each type of search result, but I've realized that this pattern will become more difficult to manage as more and more data sources are indexed by the search engine (i.e new code template has to be created for each new data source).
I created the following structure for my factory based off of an article by Granville Barnett over at DotNetSlackers.com
factory pattern http://img11.imageshack.us/img11/8382/factoryi.jpg
In order to make this search application easier to maintain, my thought was to create a set of database tables that can be used to define individual template types that my factory pattern could reference in order to determine which template to construct. I figured that I'd need to have a look up table that would be used to specify the type of template to build based off of the search result data source. I'd then need to have a table(s) to specify which fields to display for that template type. I'd also need a table (or additional columns within the template table) that would be use to define how to render that field (i.e. Hyperlink, Label, CssClass, etc).
Does anyone have any examples of a pattern like this? Please let me know.
Thanks,
-Robert
I would offer that this proposed solution is no less maintainable than simply associating a data source to the code template, as you currently have now. In fact, I would even go so far as to say you're going to lose flexibility by pushing the template schema and rendering information to a database, which will make your application harder to maintain.
For example, let's suppose you have these data sources with attributes (if I'm understanding this correctly):
Document { Author, DateModified }
Picture { Size, Caption, Image }
Song { Artist, Length, AlbumCover }
You then may have one of each of these data sources in your search results. Each element is rendered differently (Picture may be rendered with a preview image anchored to the left, or Song could display the album cover, etc.)
Let's just look at the rendering under your proposed design. You're going to query the database for the renderings and then adjust some HTML you are emitting, say because you want a green background for Documents and a blue one for Pictures. For the sake of argument, let's say you realize that you really need three background colors for Songs, two for Pictures, and one for Documents. Now, you're looking at a database schema change, which is promoted and pushed out, in addition to changing the parameterized template you're applying the rendering values to.
Let's say further you decide that the Document result needs a drop-down control, the Picture needs a few buttons, and Songs need a sound player control. Now, each template per data source changes drastically, so you're right back where you started, except now you have a database layer thrown in.
This is how the design breaks, because you've now lost the flexibility to define different templates per data source. The other thing you lose is having your templates versioned in source control.
I would look at how you can re-use common elements/controls in your emitted views, but keep the mapping in the factory between the template and the data source, and keep the templates as separate files per data source. Look at maintaining the rendering via CSS or similar configuration settings. For making it easier to maintain, considering exporting the mappings out as a simple XML file. To deploy a new data source, you simply add a mapping, create the appropriate template and CSS file, and drop them in to expected locations.
Response to comments below:
I meant a simple switch statement should suffice:
switch (resultType)
{
case (ResultType.Song):
factory = new SongResultFactory();
template = factory.BuildResult();
break;
// ...
Where you have the logic to output a given template. If you want something more compact than a long switch statement, you can create the mappings in a dictionary, like this:
IDictionary<ResultType, ResultFactory> TemplateMap;
mapping = new Dictionary<ResultType, ResultFactory>();
mapping.Add(ResultType.Song, new SongResultFactory());
// ... for all mappings.
Then, instead of a switch statement, you can do this one-liner:
template = TemplateMap[resultType].CreateTemplate();
My main argument was that at some point you still have to maintain the mappings - either in the database, a big switch statement, or this IDictionary instance that needs to be initialized.
You can take it further and store the mappings in a simple XML file that's read in:
<TemplateMap>
<Mapping ResultType="Song" ResultFactoryType="SongResultFactory" />
<!-- ... -->
</TemplateMap>
And use reflection et. al. to populate the IDictionary. You're still maintaining the mappings, but now in an XML file, which might be easier to deploy.
Ok, understand that I come from Cold Fusion so I tend to think of things in a CF sort of way, and C# and CF are as different as can be in general approach.
So the problem is: I want to pull a "table" (thats how I think of it) of data from a SQL database via LINQ and then I want to do some computations on it in memory. This "table" contains 6 or 7 values of a couple different types.
Right now, my solution is that I do the LINQ query using a Generic List of a custom Type. So my example is the RelevanceTable. I pull some data out that I want to do some evaluation of the data, which first start with .Contains. It appears that .Contains wants to act on the whole list or nothing. So I can use it if I have List<string>, but if I have List<ReferenceTableEntry> where ReferenceTableEntry is my custom type, I would need to override the IEquatable and tell the compiler what exactly "Equals" means.
While this doesn't seem unreasonable, it does seem like a long way to go for a simple problem so I have this sneaking suspicion that my approach is flawed from the get go.
If I want to use LINQ and .Contains, is overriding the Interface the only way? It seems like if there way just a way to say which field to operate on. Is there another collection type besides LIST that maybe has this ability. I have started using List a lot for this and while I have looked and looked, a see some other but not necessarily superior approaches.
I'm not looking for some fine point of performance or compactness or readability, just wondering if I am using a Phillips head screwdriver in a Hex screw. If my approach is a "decent" one, but not the best of course I'd like to know a better, but just knowing that its in the ballpark would give me little "Yeah! I'm not stupid!" and I would finish at least what I am doing completely before switch to another method.
Hope I explained that well enough. Thanks for you help.
What exactly is it you want to do with the table? It isn't clear. However, the standard LINQ (-to-Objects) methods will be available on any typed collection (including List<T>), allowing any range of Where, First, Any, All, etc.
So: what is you are trying to do? If you had the table, what value(s) do you want?
As a guess (based on the Contains stuff) - do you just want:
bool x= table.Any(x=>x.Foo == foo); // or someObj.Foo
?
There are overloads for some of the methods in the List class that takes a delegate (optionally in the form of a lambda expression), that you can use to specify what field to look for.
For example, to look for the item where the Id property is 42:
ReferenceTableEntry found = theList.Find(r => r.Id == 42);
The found variable will have a reference to the first item that matches, or null if no item matched.
There are also some LINQ extensions that takes a delegate or an expression. This will do the same as the Find method:
ReferenceTableEntry found = theList.FirstOrDefault(r => r.Id == 42);
Ok, so if I'm reading this correctly you want to use the contains method. When using this with collections of objects (such as ReferenceTableEntry) you need to be careful because what you're saying is you're checking to see if the collection contains an object that IS the same as the object you're comparing against.
If you use the .Find() or .FindAll() method you can specify the criteria that you want to match on using an anonymous method.
So for example if you want to find all ReferenceTableEntry records in your list that have an Id greater than 1 you could do something like this
List<ReferenceTableEntry> listToSearch = //populate list here
var matches = listToSearch.FindAll(x => x.Id > 1);
matches will be a list of ReferenceTableEntry records that have an ID greater than 1.
having said all that, it's not completely clear that this is what you're trying to do.
Here is the LINQ query involved that creates the object I am talking about, and the problem line is:
.Where (searchWord => queryTerms.Contains(searchWord.Word))
List<queryTerm> queryTerms = MakeQueryTermList();
public static List<RelevanceTableEntry> CreateRelevanceTable(List<queryTerm> queryTerms)
{
SearchDataContext myContext = new SearchDataContext();
var productRelevance = (from pwords in myContext.SearchWordOccuranceProducts
where (myContext.SearchUniqueWords
.Where (searchWord => queryTerms.Contains(searchWord.Word))
.Select (searchWord => searchWord.Id)).Contains(pwords.WordId)
orderby pwords.WordId
select new {pwords.WordId, pwords.Weight, pwords.Position, pwords.ProductId});
}
This query returns a list of WordId's that match the submitted search string (when it was List and it was just the word, that works fine, because as an answerer mentioned before, they were the same type of objects). My custom type here is queryTerms, a List that contains WordId, ProductId, Position, and Weight. From there I go about calculating the relevance by doing various operations on the created object. Sum "Weight" by product, use position matches to bump up Weights, etc. My point for keeping this separate was that the rules for doing those operations will change, but the basic factors involved will not. I would have even rather it be MORE separate (I'm still learning, I don't want to get fancy) but the rules for local and interpreted LINQ queries seems to trip me up when I do.
Since CF has supported queries of queries forever, that's how I tend to lean. Pull the data you need from the db, then do your operations (which includes queries with Aggregate functions) on the in-memory table.
I hope that makes it more clear.