Definining specific mapping rule for a field - ormlite-servicestack

I've started using ORMLite two days ago for refactoring an existing app....
I've some old stored procedure that returns columns with name that don't map 1:1 my dto object but I've managd to use [AliasAttribute] and it works fine.... at the same time I've some column that currently are mapped with some logic... for example
//Consider I've a dataset and I'm processing rows
int average = (int)row["AVERAGE"];
if(average > 50)
{
myDTO.Message = "Warning";
}
else
{
myDTO.Message = "OK";
}
Now we all agree it's not what it should be done at DataLayer but on that 5years old application we do so...is there a way I can tell in my DTO class (as I've done for Alias) to tell how to act when mapping the AVERAGE column?
Another question do ORM performs a trim on string or have I to perform it myself? again on some SP I've got no trim and I get something as "John DOE " ....now I do a .TrimEnd() when I got the value...
Thanks

Add the message as a property on your dto
public class MyDto
{
public int Average { get; set; }
public string Message
{
get { return Average > 50 ? "Warning" : "OK"; }
}
}

Related

ASP.NET MVC Entity Framework - Entity Update - Overwriting Database Values with Null Values

I am currently looking for a design pattern or rather a best practice in implementing Repository<Entity>.Update() method for a ASP.NET MVC 4 application which uses Entity Framework 5 with Code First approach.
Problem:
The problem I encountered is that when an entity is queried from the database and shown on a view it may not have all the attributes populated. As a result when the repository.Update(entity) method is invoked, the entity passed to the Update() method may have un-bound properties having null values. However they may have some values in the database. As an example Customer.Misc in below code.
So the problem comes here. According to this approach all the properties which were not bound on the view are set to Null in the database after the first Update() method call.
class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Misc { get; set; }
}
[HttpGet]
public ActionResult Update(int id)
{
Repository<Customer> repo = new Repository<Customer>();
return View(repo.GetById(id)); // View only binds Customer.Name
}
[HttpPost]
public ActionResult Update(Customer customer)
{
Repository<Customer> repo = new Repository<Customer>();
repo.Update(customer); // Customer.Misc is null
...
}
public void Update(TEntity entity)
{
var entry = DbContext.Entry<TEntity>(entity);
if (entry.State == EntityState.Detached)
{
ObjectContext.ApplyCurrentValues(EntitySetName, entity);
}
DbContext.SaveChanges();
}
Solutions I could think:
Bind all entity attributes on the view:
I think this is not feasible and at the same time it may lead to performance issues since all attributes get populated.
Implement a custom method to copy property values to avoid null values being copied.
EntityHelper.CopyNotNullValues(source, target) and ignore null values in the source entity. If we do this we might not be able to set any of the values to null if required.
Implement View Models and transform data back and forth with the Domain Model.
This is the best approach I could think of so far. All the attributes bound to the View Model will get populated always, on the Update POST, copy all View Model values to the Domain Model.
Really appreciate your thoughts on this.
In Entity Framework, using ChangeObjectState or ApplyCurrentValues will cause data loss. The only way to work around this issue in this case is attaching the input entity and mark the properties to be updated. See below example:
public void Update(TEntity entity, string[] updatedProperties)
{
DbContext.Entities.Attach(entity);
var entry = DbContext.Entry<TEntity>(entity);
for (int i = 0; i < updatedProperties.Length; i++)
{
entry.SetModifiedProperty(updatedProperties[i]);
}
DbContext.SaveChanges();
}
[HttpPost]
public ActionResult Update(Customer customer)
{
Repository<Customer> repo = new Repository<Customer>();
repo.Update(customer, new string[]{ "Name" }); // Only update name
...
}
It's the best solution I can think of. You wanna have least code and good performance. It's as difficult as finding an easy and well paid job.

WCF DataContract with custom List Attribute

I have a WCF webservice, that exposes these classes:
[DataContract]
public class TemplatesFormat
{
List<DynAttribute> _dynsattributes = new List<DynAttribute>();
[DataMember]
public List<DynAttribute> DynsAttributes
{
get { return _dynsattributes; }
set { _dynsattributes = value; }
}
}
[DataContract]
public class DynAttribute
{
string _key = "";
string _val = "";
[DataMember]
public string Key
{
get { return _key; }
set { _key = value; }
}
[DataMember]
public string Value
{
get { return _val; }
set { _val = value; }
}
}
Basically, 2 classes. DynAttribute with 2 string attributes and TemplatesFormat, with an attribute that is a List of DynAttribute class.
So far, so good.
But, when I reference the web service from an ASP.NET web page and try to use the TemplatesFormat, I can't see the List attribute.
I mean, I actually "see" it, but it is not a list (does not contain an "Add()") and I don't know how to use it.
I think I am missing something related with de [DataContrat] and the fact that it is a custom type, since, I don't have the same problem with DynAttribute class (I see the Key and Value attributes because they are strings) but, I can't get it right for the List...
Any idea???
When you add reference to wcf service you need to change Collection Type to Generic List.
Please see my post wcf-proxy-returning-array-instead-of-list-even-though-collection-type-generic for more details and snipp picture.
WCF is meant to support consumption by many other platforms. Because List<DynAttribute> is not a primitive type, it is likely converting it to DynAttribute[].
In your consuming application. Try taking your variable and seeing if you can .ToList() it to turn it back into the List<DynAttribute> you're expecting.

Error displaying details (ObjectContext instance has been disposed)

I'm building an ASP.NET MVC 3 app and I've got a model that looks something like so:
public partial class Flavor
{
// ...
public string Name { get; set; }
public bool HasNuts {get; set; }
public virtual ICollection<SaleData> Sales {get; set;}
// ...
}
which retrieves some data from a db as such:
public PartialViewResult Details(int id)
{
using (var db = new IceCreamDBFlavors())
{
Flavor someFlavor = db.Flavors.Find(id);
someFlavor.Sales = db.Sales.Where(c => c.FlavorID == id).ToList();
return PartialView("details", someFlavor);
}
}
over on the view I do something like this:
<fieldset>
<legend>Sales Data</legend>
#foreach (var sale in Model.Sales)
{
<div>Weekly</div>
<div>#sale.Weekly</div>
}
</fieldset>
If I don't retrieve the Sales data, my Flavor data displays fine with no errors, but adding the call to retrieve the list of sales data causes an error "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection." to occur.
I've read a few other posts about this and guess I'm missing something here. I believe this error happens due to lazy loading, at least based on what I've read here and elsewhere. Setting a breakpoint in the Controller before returning the PartialView and checking the object, I believe, causes the evaluation to take place, so everything displays as I would want.
I was under the impression that the ToList() call would force the Sales collection to be filled in. Since I don't have the issue when that line's commented out, I assume the problem is still related to that and when the View is attempting to iterate the Sales, it can't. Am I correct here? I guess I thought I was forcing the evaluation. How do I resolve this?
My suspicion is that Flavor has other collections (and not just Sales) and it is in fact at the time of accessing those that it breaks.
Here you are replacing only Sales while other collections or complex properties would still need the object context.
Don't dispose the IceCreamDBFlavors class that inherits from ObjectContext, it needs to have a lifetime greater than is currently allowed.
Change
using (var db = new IceCreamDBFlavors())
{
Flavor someFlavor = db.Flavors.Find(id);
someFlavor.Sales = db.Sales.Where(c => c.FlavorID == id).ToList();
return PartialView("details", someFlavor);
}
To
try
{
var db = new IceCreamDBFlavors();
Flavor someFlavor = db.Flavors.Find(id);
someFlavor.Sales = db.Sales.Where(c => c.FlavorID == id).ToList();
return PartialView("details", someFlavor);
}
catch(Exception ex)
{
// log exeption
}

S#arp Architecture + NHibernate.Search + DocumentId

I’m new to NHibernate.Search and i’ve ran into a problem I need a little help with.
I need to add a [DocumentId] attribute to my ID field, but the Id field is in the Entity class...I found some code on stackoverflow that done this inside my POCO:
[DocumentId]
public virtual int Id
{
get { return base.Id; }
protected set { base.Id = value; }
}
But when I run the UpdateModel() function in my controller, I get an exception:
Exception Details:
System.Reflection.AmbiguousMatchException:
Ambiguous match found.
I think the model binder is seeing 2 Id fields, however i’m not sure of the best way around this.
Paul
I'll answer my own question on this one after a tinkering around a little.
[DocumentId]
public override int Id
{
get
{
return base.Id;
}
protected set { base.Id = value; }
}
Paul

ASP.NET; Several session variables or a "container object"?

I have several variables that I need to send from page to page...
What is the best way to do this?
Just send them one by one:
string var1 = Session["var1"] == null ? "" : Session["var1"].ToString();
int var2 = Session["var2"] == null ? 0 : int.Parse(Session["var2"].ToString());
and so on...
Or put them all in some kind of container-object?
struct SessionData
{
public int Var1 { get; set; }
public string Var2 { get; set; }
public int Var3 { get; set; }
}
--
SessionData data = Session["data"] as SessionData;
What is the best solution? What do you use?
A hybrid of the two is the most maintainable approach. The Session offers a low-impedance, flexible key-value pair store so it would be wasteful not to take advantage of that. However, for complex pieces of data that are always related to each other - for example, a UserProfile - it makes sense to have a deeply nested object.
If all the data that you're storing in the Session is related, then I would suggest consolodating it into a single object like your second example:
public class UserData
{
public string UserName { get; set; }
public string LastPageViewed { get; set; }
public int ParentGroupId { get; set; }
}
And then load everything once and store it for the Session.
However, I would not suggest bundling unrelated Session data into a single object. I would break each seperate group of related items into their own. The result would be something of a middleground between the two hardline approaches you provided.
I use a SessionHandler, which is a custom rolled class that looks like this
public static class SessionHandler
{
public static string UserId
{
get
{
return Session["UserId"];
}
set
{
Session["UserId"] = value;
}
}
}
And then in code I do
var user = myDataContext.Users.Where(u => u.UserId = SessionHandler.UserId).FirstOrDefault();
I don't think I've every created an object just to bundle other objects for storage in a session, so I'd probably go with the first option. That said, if you have such a large number of objects that you need to bundle them up to make it easier to work with, you might want to re-examine your architecture.
I've used both. In general, many session variable names leads to a possibility of collisions, which makes collections a litte more reliable. Make sure the collection content relates to a single responsibility, just as you would for any object. (In fact, business objects make excellent candidates for session objects.)
Two tips:
Define all session names as public static readonly variables, and make it a coding standard to use only these static variables when naming session data.
Second, make sure that every object is marked with the [Serializable] attribute. If you ever need to save session state out-of-process, this is essential.
The big plus of an object: properties are strongly-typed.

Resources