Use external expression in linq query - linq-to-sql

I need to use an expression defined outside my query. This expression will be used in many other queries so I would like to reuse that.
This is a simple sample to illustrate.
repos.ItemDocumentoProprio.Select(s => new SaleDto {
Total = s.Total,
TotalSale = s.CalcTotalSale()
});
public class Sale
{
public int Id { get; set; }
public decimal Total { get; set; }
public decimal Discount { get; set; }
public Expression<Func<Sale, decimal>> CalcTotalSale()
{
return (s => s.Total - s.Discount);
}
}
This code doesn't compile because cannot implicity convert Expression> to decimal as I expected.

If you're looking to dynamically build your SELECT query in LINQ to Entities AND have reusable methods, that is a more advanced topic which I won't attempt to cover in this answer.
While it isn't clear what your "other queries" will look like, I'd like to point out an alternative approach that may help you think about Expressions differently. You could do the following:
repos.ItemDocumentoProprio.Select(Sale.GetSaleDto());
public class Sale
{
public int Id { get; set; }
public decimal Total { get; set; }
public decimal Discount { get; set; }
public static Expression<Func<Sale, SaleDto>> GetSaleDto()
{
// As mentioned in my response, if you need to build this expression dynamically at
// runtime for different data calls to the DB store, that is a more advanced task.
Expression<Func<Sale, SaleDto>> selectFunc = s => new SaleDto
{
Total = s.Total,
TotalSale = s.Total - s.Discount
};
return selectFunc;
}
}
Another alternative is making the TotalSale property in SaleDto a calculated property. If you want the TotalSale calculation (Total - Discount) to be available in other DTO classes, then make a new method elsewhere that accepts two arguments (Total, Discount) and returns a decimal and reuse that throughout. Better yet, move it into an interface/abstract base class that all of your Sale-like classes must implement.
public class SaleDto
{
public decimal Total { get; set; }
public decimal Discount { get; set; }
public decimal TotalSale
{
get { return Total - Discount; }
}
}
The only difference here is you are performing the TotalSale calculation in memory as opposed to in the RDBMS. Without doing any formal analysis, I'm guessing the performance difference is negligible and the data sent over the wire from the DB to app is going to be of similar size.

Related

Enity Framework Core: Handling large number of enum-like fields

I am currently facing the following problem:
I have a model class LargeDataClass with many fields (200+).
Many of these fields (~50-80) are enum-like (i.e. they can be filled out with certain sets of options in the UI).
Now my approach was to model these as enum classes, like
[Table("tbl_enum_one")]
class EnumOne {
public int ID { get; set; }
public string Name { get; set; }
}
[Table("tbl_large_dataclass")]
class LargeDataClass {
public EnumOne EnumOne { get; set; }
public int EnumOneId { get; set; }
//...
}
This has the major advantage of being easily extendable (to add a dropdown option in the UI, just add a row to the table).
Now I am facing some concerns/problems:
When I fetch my model class LargeDataClass from the DB with all its enum fields included, there will be a lot of joins (as I stated above, there are like 50 to 80 of these fields). I am worried that will have a big impact on query performance. Plus create/update/delete might be quite slow due to the large number of indexes to be updated.
MySQL won't even let me create a table tbl_large_dataclass with that many FKs (too many indexes on a single table).
So now I am considering two (in my view really unfortunate) options:
Using regular enums, so no enum classes with their own tables, storing them as simple int/string fields in the DB. This would cause no performance concerns at all, but unfortunately, the 'live' extendability is quite important, so this option would only be the last resort.
Using the Enum classes, but having just the ID of the enum in the LargeDataClass, so kind of keeping the fact that this is a foreign key secret from the DB. If I wanted to display a LargeDataClass object somewhere, I would have to separately fetch the enum classes. Plus I would have to make extra sure everywhere that I only use Ids that are really present in the enum table.
I am really unsure what would be the best approach here.
Database is not an object store and you have to design it accordingly. I have changed you schema and only two tables are needed for storing dropdown values.
[Table("tbl_enum_type")]
public class EnumType {
public int ID { get; set; } // PK
public string Name { get; set; }
}
// PK (EnumTypeId, Id) - reusing the same index for dropdown generation
[Table("tbl_enum_value")]
public class EnumValue {
public int ID { get; set; }
public string Name { get; set; }
public int Order { get; set; } // for dropdown ordering
public int EnumTypeId { get; set; }
public EnumType EnumType { get; set; }
}
// store only ID's, no FK
[Table("tbl_large_dataclass")]
public class LargeDataClass {
public int EnumOneId { get; set; } // EnumTypeId 1
public int EnumSecondId { get; set; } // EnumTypeId 2
//...
}
For generating dropdowns, you have to cache EnumType and EnumValue tables in memory in useful structure.
Override method SaveChanges/SaveChangesAsync and check saved Id's according to cached data.
It will not help if your database is changed via SQL, but here we have trade-off between performance and consistency. Probably good trigger may help here.
UPDATE:
Consider to restructure LargeDataClass to two tables
[Table("tbl_option_bag")]
public class OptionBag {
public int Id { get; set; }
public ICollection<Option> Options { get; set; }
}
[Table("tbl_options")]
public class Option {
public int Id { get; set; }
public int OptionBagId {get; set; }
public int EnumTypeId { get; set; }
public int EnumId { get; set; }
//...
}
Here you can use FK and DTO can be generated on selecting Options navigation property.

Using json key to store value, is it a good approach?

I am writing a rest api and I am quite new to the json serialization.
I know that a json object consists of pairs of <key>:<value>.
I have an object "channels" which contains multiple channel objects which consist of an id and some other attributes like "x", "y" and "z".
In our team we found two ways to represent the object "channels", the usual way that I see people implement is like this:
{
"channels":
[
{
"id":0,
"x":0,
"y":0,
"z":0
},
...
]
}
There is also this version, which uses the id as key:
{
"channels":
{
"0":
{
"x":0,
"y":0,
"z":0
},
...
}
}
Please note that the first implementation explicitily uses an array while the second relies on the <key> to access the specific channel directly.
What is the best way to represent this object? Is it ok to represent a key as value (like the id of the previous case)?
Right now there are only two channels (always with id 0 and 1), but in the future we may add more.
You should prefer the first approach, because it is much easier and more intuitive to consume the JSON that way. If someone wanted to use your API, they would likely create model classes to deserialize into. With the first approach this is easy:
public class RootObject
{
public List<Channel> channels { get; set; }
}
public class Channel
{
public int id { get; set; }
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
}
In fact, you can just take the JSON and dump it into a generator tool like http://json2csharp.com/ to get these classes (that is what I did here).
In contrast, with the second approach, the keys in the JSON representing the IDs are dynamic, which a generator won't recognize as such. So you'll get something like this, which needs to be manually corrected:
public class RootObject
{
public Channels channels { get; set; }
}
public class Channels
{
public __invalid_type__0 __invalid_name__0 { get; set; }
}
public class __invalid_type__0
{
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
}
I've seen some people try to fix it like this, which will work for your one-channel example, but obviously won't scale:
public class RootObject
{
public Channels channels { get; set; }
}
public class Channels
{
[JsonProperty("0")]
public Data Item0 { get; set; }
}
public class Data
{
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
}
To consume the JSON properly with the dynamic keys, the classes actually need to look like this:
public class RootObject
{
public Dictionary<string, Channel> channels { get; set; }
}
public class Channel
{
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
}
However, the fact that you need to use a Dictionary here is not always intuitive to the casual user. In fact, I have lost count of the number of times some flavor of the question, "How can I handle dynamic keys in JSON?" is asked on StackOverflow. Do your users a favor and don't make them have to think about it.
Over and above just deserializing the JSON, the first model is also superior because the Channel object contains all the data about the channel: the id is inside the object itself. It is easy to pass around and use that way. Also it is trivial to convert a List<Channel> into a Dictionary<int, Channel> later if you need to do a key lookup:
var dict = rootObject.channels.ToDictionary(ch => ch.id);
With the second approach, the id is separate from rest of the channel data, so if you wanted to pass the channel to a method which needed both, you would either have to pass two parameters or create a new model class to wrap everything together. In other words, it is more awkward to use.
Bottom line, I see no real upside to using the second approach at all. Go with the first.
If a channel is an object, not an array then you should use the first option, as you define channel specific contract. If a channel can have subsets of channels, then I suggest using the second approach as you can gain an access to specific subset via the use of a key ( which has to be unique in order to work properly ).

EntityFramework Include and possibly join?

I have the following table structure as shown in the picture. (see: Table structure). Both tables ("Batches" and "Methods") reference to a "Project" table.
When I now create a new Project I would like to get all childs created as well.
Doing so I did the follwoing:
_dbContext.Projects.Where(x => x.Id == prjId)
.Include(x => x.Batches)
.Include(x => x.Batches.Select(y => y.Measurements))
.Include(x => x.Methods).AsNoTracking().FirstOrDefault();
Now the problem is the following:
New Batch and Method instances are created - thus they get a new ID(PK). The referenced Project_Id (FK) is set correct. But in my new Measurement instance only the Batch_Id(FK) is set correct and the Method_Id remains unchanged (has the old value) (see: result).
What I need is that the Measurements.Mehtod_Id is set from the Methods table. Is there any suitable solution for that?
My entities look like the following
public class Project
{
[Key]
public long Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public virtual List<Batch> Batches { get; set; }
public virtual List<Method> Methods { get; set; }
}
public class Batch : BaseObject
{
public Batch()
{
BatchFiles = new List<FileAttachment>();
Measurements = new List<Measurement>();
}
public long Id { get; protected set; }
public long Project_Id { get; set; }
public virtual Project Project { get; set; }
public virtual List<Measurement> Measurements { get; set; }
}
public class Method : BaseObject
{
public Method()
{
Parameters = new List<Parameter>();
}
public long Id { get; protected set; }
public long Project_Id { get; set; }
public virtual Project Project { get; set; }
public virtual List<Measurement> Measurements { get; set; }
}
public class Measurement
{
public int Id { get; protected set; }
[ForeignKey("Batch")]
public long? Batch_Id { get; set; }
[Required]
public virtual Batch Batch { get; set; }
[ForeignKey("Method")]
public long? Method_Id { get; set; }
public virtual Method Method { get; set; }
}
// creation code (just a copy with new IDs for all childs)
Project newProjectVersion = _dbContext.Projects.Where(x => x.Id == prjId)
.Include(x => x.Batches)
.Include(x => x.Batches.Select(y => y.Measurements))
.Include(x => x.Methods)
.AsNoTracking().FirstOrDefault();
_dbContext.Projects.Add(newProjectVersion);
_dbContext.SaveChanges();
Thanks for any help!
The first problem is that your Select statement doesn't connect Measurements to Methods because of the AsNoTracking() addition. Only Projects and Methods are connected because they are explicitly Included off of the Project entity. The Measurements have a Method_id but this is value is not accompanied by a Method in their Method property. You could check that in the debugger if you walk through the object graph (with lazy loading disabled though!). Because of this, when all entities will be Add-ed to the context, EF won't notice that measurements receive new methods.
You could get tempted to fix that by Include-ing Measurement.Method as well:
...
.Include(x => x.Batches.Select(y => y.Measurements.Select(m => m.Method)))
...
Now you'll see that Measurement.Method will be populated everywhere in the object graph.
However, there's a gotcha here. When using AsNoTracking, EF6 doesn't keep track of entities it materialized (duh). This means that for each Measurement it creates a new Method instance, even if an identical Method (by id) was materialized before for another Measurement. (And in this case it will always materialize duplicates, because you already include Project.Methods.)
That's why you can't do this in the quick way with AsNoTracking and Add using one context instance. You'll get an error that EF tries to attach duplicate entities.
You must build the object graph using one context, with tracking, so EF will not materialize duplicates. Then you must Add this object graph to a new context. Which will look like this:
Project project;
using(var db = new MyContext())
{
db.Configuration.ProxyCreationEnabled = false;
project = db.Projects.Where(x => x.Id == prjId)
.Include(x => x.Batches)
.Include(x => x.Batches.Select(y => y.Measurements))
.Include(x => x.Methods).FirstOrDefault();
}
using(var db = new MyContext())
{
db.Projects.Add(project);
db.SaveChages();
}
Three remarks:
Proxy creation is disabled, because you can't attach a proxy to another context without explicitly detaching it first.
No, I didn't forget to include Measurement.Method. All methods are loaded by including them in the Project and now (because of tracking, and assuming that measurement will only have methods of the project they belong to), EF connects them with the Measurements by relationship fixup.
EF-core is smarter here: when adding AsNoTracking it won't track materialized entities, but still, it won't create duplicates either. It seems to have some temporary tracking during the construction of an object graph.
thanks for your answer so far. This works quite fine right now. Unfortunately I noticed that the Measurements entity has another required relationship to a table named 'MeasurementTypes':
[Required]
public virtual MeasurementType MeasurementType { get; set; }
[ForeignKey("MeasurementType")]
public long MeasurementType_Id { get; set; }
In contrast to Batches and Methods these entries must not be copied and the entries already exist in the MeasrementTypes table.
What would be a good way to put the required reference to the Measurements?

Migrating from LINQ to SQL to Entity Framework "Code First"

As I already have classes for my LINQ to SQL data access solution, what trouble might I run into if I wanted to migrate them over to EFCF instead? I'm hesistant to call this code first as the database does already exist. To be clear, the application is not yet in production so if EFCF wipes out the data it's no real loss.
Can I take a class such as the one that follows and simply use it in EFCF? Should I or must I remove the data annotation attributes?
What needs to change where I have EntityRef and EntitySet?
[Table]
public class PlanMember {
private EntityRef<SystemUser> _caseManager;
private EntityRef<PlanMemberStatus> _status;
public PlanMember() {
this.PlanMemberView = new Views.PlanMember();
}
[Column(
IsPrimaryKey = true,
IsDbGenerated = true,
AutoSync = AutoSync.OnInsert
)]
public Int64 ID { get; set; }
[Column]
public DateTime? BirthDate { get; set; }
[Column]
public String City { get; set; }
[Column]
public String FirstName { get; set; }
[Association(ThisKey = "CaseManagerID", Storage = "_caseManager")]
public SystemUser CaseManager {
get { return (this._caseManager.Entity); }
set { this._caseManager.Entity = value; }
}
[Column]
public String CaseManagerID { get; set; }
[Column]
public Boolean IsActive { get; set; }
public Boolean IsEligible {
get { return (this.PlanMemberView.IsEligible); }
}
[Column]
public String LastName { get; set; }
[Column]
public String MedicalRecord { get; set; }
[Column]
public String MemberNumber { get; set; }
[Column(Name = "PCPFullName")]
public String PrimaryCarePhysicianFullName { get; set; }
[Association(OtherKey = "PlanMemberID")]
public Views.PlanMember PlanMemberView { get; set; }
[Column]
public Int32 PostalCode { get; set; }
[Column]
public String Sex { get; set; }
[Column]
public String State { get; set; }
[Association(ThisKey = "StatusID", Storage = "_status")]
public PlanMemberStatus Status {
get { return (this._status.Entity); }
set { this._status.Entity = value; }
}
[Column]
public Int32 StatusID { get; set; }
}
We migrated an application from Linq to Sql to EF POCO generation but haven't tried code first as it wasn't baked at the time. Was really not horribly difficult. The main pain point in our case was the following differences:
Linq to Sql handles many to many relationships using a separate "bridge" object, EF treats those relationships as collections of various sorts. This changes lots of semantics and can cause lots of code to change, especially if you let entities creep into the UI.
Another pain point was nullable and non-nullable relationships. Linq to Sql was a bit more forgiving here, but for EF to play well we needed to allow nullable columns some places we traditionally had not.
Linq to Sql and EF data mapping sometimes have different ideas about what CLR types to map to. Xml columns were our major pain point but you might not have any of those.
Big trick/nightmare was how to get rid of the l2s bits without breaking everything horribly as linq to sql generates your entities.
This is not something I would try without a pretty effective set of unit tests to give you an automated basis to give you pretty regular temperature readings. Our other godsend was we had a pretty solid Repository pattern implementation -- nothing was talking directly to the EF/Linq2Sql bits but two classes implementing IRepository. Basically, this is a great test for how disciplined you were in implementing your architecture. Also, it is an occasion when you realize that resharper is worth every cent.
To answer your one direct question, I don't think the attributes will necessarily matter but I would remove them so as not to have any potential confusion and/or namespace collisions.
Assuming your classes are named the same as your database tables, and the properties of your classes match the database column names, you should be able to delete all the attributes and use these same classes as your EF code-first model (I don't think you have to delete the attributes, but unless you plan to continue using them in a Linq2Sql model, there's no reason to keep them, and since some things will probably change in the migration, it would probably be best to delete them since your new entities may not still be able to work in Linq2Sql). If your classes don't match your database schema, Scott Guthrie has a blog post about Entity Framework 4 "Code-First": Custom Database Schema Mapping.
What needs to change where I have EntityRef and EntitySet?
A relation defined as EntityRef<OtherEntity> can be replaced with a property of just type OtherEntity, and an EntitySet<OtherEntity> can become an ICollection<OtherEntity> or anything that implements ICollection<T> such as an IDbSet<OtherEntity> (I believe a DbSet<T> is what you would get if you were generating the model from your existing database).

Applying Domain Model on top of Linq2Sql entities

I am trying to practice the model first approach and I am putting together a domain model. My requirement is pretty simple: UserSession can have multiple ShoppingCartItems.
I should start off by saying that I am going to apply the domain model interfaces to Linq2Sql generated entities (using partial classes). My requirement translates into three database tables (UserSession, Product, ShoppingCartItem where ProductId and UserSessionId are foreign keys in the ShoppingCartItem table). Linq2Sql generates these entities for me. I know I shouldn't even be dealing with the database at this point but I think it is important to mention.
The aggregate root is UserSession as a ShoppingCartItem can not exist without a UserSession but I am unclear on the rest. What about Product? It is defiently an entity but should it be associated to ShoppingCartItem?
Here are a few suggestion (they might all be incorrect implementations):
public interface IUserSession {
public Guid Id { get; set; }
public IList<IShoppingCartItem> ShoppingCartItems{ get; set; }
}
public interface IShoppingCartItem {
public Guid UserSessionId { get; set; }
public int ProductId { get; set; }
}
Another one would be:
public interface IUserSession {
public Guid Id { get; set; }
public IList<IShoppingCartItem> ShoppingCartItems{ get; set; }
}
public interface IShoppingCartItem {
public Guid UserSessionId { get; set; }
public IProduct Product { get; set; }
}
A third one is:
public interface IUserSession {
public Guid Id { get; set; }
public IList<IShoppingCartItemColletion> ShoppingCartItems{ get; set; }
}
public interface IShoppingCartItemColletion {
public IUserSession UserSession { get; set; }
public IProduct Product { get; set; }
}
public interface IProduct {
public int ProductId { get; set; }
}
I have a feeling my mind is too tightly coupled with database models and tables which is making this hard to grasp. Anyone care to decouple?
Looks like you are on the right track. Half of the whole "doing DDD right" is having the right base classes. Have a look at this great DDD applied to C# resource:
http://dddpds.codeplex.com/
The source code is available and is very readable.
So, with regards to having ID in the model. The ID is a database thing and the usual approach is to keep all persistence out of the Model and restrict the model to the business logic. However, one normally makes an exception for the identifier and buries it in the Model base class like so:
public class ModelBase {
protected readonly object m_Key;
public ModelBase(object key) {
m_Key = key;
}
}
This key is used by your persistence layer to talk to the database and is opaque. It's considered quite OK to downcast the key to the required type, because you know what it is.
Also, the Domain Objects are pretty much on the bottom of your architecture stack (just above the Infrastructure layer). This means that you can make them concrete classes. You will not have multiple implementations of the domain models, so the interfaces are unnecessary, which is what Domain Driven Design is about - Domain first.
public Class UserSession : ModelBase {
public UserSession(Guid Id):base(Id) {}
public Guid Id { get{ return m_Key as Guid;} }
public IList<ShoppingCartItem> ShoppingCartItems{ get; set; }
}
public class ShoppingCartItem : ModelBase {
public ShoppingCartItem ():base(null) {}
public UserSession UserSession { get; set; }
public Product Product { get; set; }
}
Typical shopping cart or customer-order examples prefer making UserSession (or Order) the root of aggregate. Individual items should be children of this session/order. It is up you whether individual items in the cart should have a meaningful id. I would prefer no, since 5 widgets in the cart are indistinguishable from another 5 widgets. Hence, I would model cart items as a collection of value objects.
Common problem with shopping cart items is whether they should include price, or not. if you include price, you will have your cart independent from changes of product price. It is very desirable if you want to store you cart for historical reasons since it is valuable to know how much items in the cart cost according to price when they were bought, not according to current.
Product should form definitively an aggregate by itself. Period.
Now, I don't know if all of this is easily implementable in LINQ to SQL, but you can try.