Linq2Sql custom mapping - c#

My question is: is there a way with a DataContext/Table mapping to implement some custom mapping code between the database and the creation of my entity instance?
For a simple example, say that my Products entity class has property "double Length {get; set; }"
and my entity and all my existing code is expecting Length to be in Feet, but in the database Length is stored in meters so I need to do a conversion. Is there a way to register a callback or otherwise insert some code to set object.Length manually based on a DataRow or however the data is retrieved internally by L2S ?
Yes, I thought I could set "double LengthInMeters { set { Length=value*0.3048; } }" but I was hoping to avoid making duplicate properties and introducing ambiguity about which to use. What I'd like to do is register a closure with my DataContext to be called after a Product is created so that I can say:
DataContext.Entity<Product>().OnCreated( (p, row) =>
{
p.Length = row["Length"] * 0.3048;
p.ProductCode = row["Sku"].ToString().Substring(1, 5);
...etc..
});

You can do it in the post creation. the .designer.cs class contains the OnCreated() Extensibility Method for your models. You can put it there. I would not do this however. It hides important logic. Place this code in your repository or some similar abstraction. I personally would probably get the model, then transfer the data to an application specific model before returning it from the repository. Then I'd convert it back when returning it to the repository. Not very speedy, but business apps dont usually require millisecond speeds where I work... maintainability is paramount instead.

Rather than do a post-creation event, I would suggest you simply do the conversion when you instantiate your entity. For example:
var qry = from product in dc.Products
where product == something
select new Product()
{
Length = product.Length * 0.3048,
// etc.
};
var normalizedProduct = qry.ToList();

Related

The Include property lambda expression [...] is invalid. The expression should represent a property access

I'm trying to get all the Hotfix and include all the details (associated with it) where the property Available is 1. This is my code:
public static IList<HotFix> GetAllHotFix()
{
using (Context context = new Context())
{
return context.HotFix
.Include(h => h.AssociatedPRs)
.Include(h => h.Detail.Where(d => d.Available = 1))
.ToList();
}
}
And I'm getting that error. I tried using .ThenInclude but couldn't solve it.
Inside HotFix I have:
[Required]
public virtual List<HotFixDetail> Detail { get; set; }
Although you forgot to write your class definitions, it seems that you have a HotFix class. Every HotFix has a sequence of zero or more AssociatedPRs and a sequence of zero or more Details.
Ever Detail has at least one numeric property Available.
You want all HotFixes, each with all its AssociatedPRs, and all Details that have a property Available value equal to 1 (didn't you mean that available is a Boolean?)
When using entity framework, people tend to use include to get an item with its sub-items. This is not always the most efficient method, as it gets the complete row of a table, inclusive all the properties that you do not plan to use.
For instance, if you have a one-to-many relationship, Schools with their Students, then each Student will have a foreign key to the School that this `Student attends.
So if School [10] has 1000 Students, then every Student will have a foreign key to the School with a value 10. If you use Include to fetch School [10] with its Students, then this foreign key value is also selected, and sent a 1000 times. You already know it will equal the Schools primary key value, hence it is a waste of processing power to transport this value 10 a 1001 times.
When querying data, always use Select, and Select only the properties you actually plan to use. Only use Include if you plan to update the fetched data.
Another good advice is to use plurals to describe sequences and singulars to describe one item in your sequence
Your query will be:
var result = context.HotFixes.Select(hotfix => new
{
// Select only the hotfix properties you actually plan to use:
Id = hotfix.Id,
Date = hotfix.Date,
...
AssociatedPRs = hotfix.AssociatedPRs.Select(accociatedPr => new
{
// again, select only the associatedPr properties that you plan to use
Id = associatedPr.Id,
Name = associatedPr.Name,
...
// foreign key not needed, you already know the value
// HotFixId = associatedPr.HotFixId
})
.ToList(),
Details = hotfix.Details
.Where(detail => detail.Available == 1)
.Select(detail => new
{
Id = detail.Id,
Description = detail.Description,
...
// not needed, you know the value:
// Available = detail.Available,
// not needed, you know the value:
// HotFixId = detail.HotFixId,
})
.ToList(),
});
I used anonymous type. You can only use it within the procedure in which the anonymous type is defined. If you need to return the fetched data, you'll need to put the selected data in a class.
return context.HotFixes.Select(hotfix => new HotFix()
{
Id = hotfix.Id,
Date = hotfix.Date,
...
AssociatedPRs = hotfix.AssociatedPRs.Select(accociatedPr => new AssociatedPr()
{
... // etc
Note: you still don't have to fill all the fields, unless your function requirement specifically states this.
It might be confusing for users of your function to not know which fields will actually be filled and which ones will not. On the other hand: when adding items to your database they are already accustomed not to fill in all fields, for instance the primary and foreign keys.
As a solution for that not all fields are filled, some developers design an extra layer: the repository layer (using the repository pattern). For this they create classes that represent the data that people want to put into storage and want to save into the storage. Usually those people are not interested in that the data is saved in a relational database, with foreign keys and stuff. So the repository classes won't have the foreign keys
The advantage of the repository pattern is, that the repository layer hides the actual structure of your storage system. It even hides that it is a relational database. It might also be in a JSON-file. If the database changes, users of the repository layer don't have to know about this, and probably don't need to change as well.
A repository pattern also makes it easier to mock the database for unit testing: since users don't know that the data is in a relational database, for the unit test you can save the date in a JSON file, or a CSV-file or whatever.
The disadvantage is that you need to write extra classes that holds the data that is to be put into the repository, or fetched from the repository.
Whether it is wise to add this extra layer or not, depends on how often you expect your database to change layout in the future, and how good your unit tests need to be.

Entity Framework updating two databases

As I've mentioned in a couple other questions, I'm currently trying to replace a home-grown ORM with the Entity Framework, now that our database can support it.
Currently, we have certain objects set up such that they are mapped to a table in our internal database and a table in the database that runs our website (which is not even in the same state, let alone on the same server). So, for example:
Part p = new Part(12345);
p.Name = "Renamed part";
p.Update();
will update both the internal and the web databases simultaneously to reflect that the part with ID 12345 is now named "Renamed part". This logic only needs to go one direction (internal -> web) for the time being. We access the web database through a LINQ-to-SQL DBML and its objects.
I think my question has two parts, although it's possible I'm not asking the right question in the first place.
Is there any kind of "OnUpdate()" event/method that I can use to trigger validation of "Should this be pushed to the web?" and then do the pushing? If there isn't anything by default, is there any other way I can insert logic between .SaveChanges() and when it hits the database?
Is there any way that I can specify for each object which DBML object it maps to, and for each EF auto-generated property which property on the L2S object to map to? The names often match up, but not always so I can't rely on that. Alternatively, can I modify the L2S objects in a generic way so that they can populate themselves from the EF object?
Sounds like a job for Sql Server replication.
You don't need to inter-connect the two together as it seems you're saying with question 2.
Just have the two separate databases with their own EF or L2S models and abstract them away using repositories with domain objects.
This is the solution I ended up going with. Note that the implementation of IAdvantageWebTable is inherited from the existing base class, so nothing special needed to be done for EF-based classes, once the T4 template was modified to inherit correctly.
public partial class EntityContext
{
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
var modified = this.ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added); // Get the list of things to update
var result = base.SaveChanges(options); // Call the base SaveChanges, which clears that list.
using (var context = new WebDataContext()) // This is the second database context.
{
foreach (var obj in modified)
{
var table = obj.Entity as IAdvantageWebTable;
if (table != null)
{
table.UpdateWeb(context); // This is IAdvantageWebTable.UpdateWeb(), which calls all the existing logic I've had in place for years.
}
}
context.SubmitChanges();
}
return result;
}
}

Is there a design pattern for light & heavy versions of an object?

I have the need for both light-weight, and heavy-weight versions of an object in my application.
A light-weight object would contain only ID fields, but no instances of related classes.
A heavy-weight object would contain IDs, and instances of those classes.
Here is an example class (for purpose of discussion only):
public class OrderItem
{
// FK to Order table
public int OrderID;
public Order Order;
// FK to Prodcut table
public int ProductID;
public Product Product;
// columns in OrderItem table
public int Quantity;
public decimal UnitCost;
// Loads an instance of the object without linking to objects it relates to.
// Order, Product will be NULL.
public static OrderItem LoadOrderItemLite()
{
var reader = // get from DB Query
var item = new OrderItem();
item.OrderID = reader.GetInt("OrderID");
item.ProductID = reader.GetInt("ProductID");
item.Quantity = reader.GetInt("Quantity");
item.UnitCost = reader.GetDecimal("UnitCost");
return item;
}
// Loads an instance of the objecting and links to all other objects.
// Order, Product objects will exist.
public static OrderItem LoadOrderItemFULL()
{
var item = LoadOrderItemLite();
item.Order = Order.LoadFULL(item.OrderID);
item.Product = Product.LoadFULL(item.ProductID);
return item;
}
}
Is there a good design pattern to follow to accomplish this?
I can see how it can be coded into a single class (as my example above), but it is not apparent in which way an instance is being used. I would need to have NULL checks throughout my code.
Edit:
This object model is being used on client side of client-server application. In the case where I'm using the light-weight objects, I don't want lazy load because it will be a waste of time and memory ( I will already have the objects in memory on client side elsewhere)
Lazy initialization, Virtual Proxy and Ghost are three implementations of that lazy loading pattern. Basically they refer to load properties once you need them. Now, I suppose you'll be using some repo to store objects so I'll encourage you to use any of the ORM tools available. (Hibernate, Entity Framework and so on), they all implement these functionality free for you.
Have you considered using an ORM tool like NHibernate for accessing DB? If you use something like NHibernate, you would get this behavior by means of lazy loading.
Most ORM tools do exactly what you are looking for within lazy loading - they first get the object identifiers, and upon accessing a method, they issue subsequent queries to load the related objects.
Sounds like you might have a need for a Data Transfer Object (DTO), just a "dumb" wrapper class that summarizes a business entity. I usually use something like that when I need to flatten out an object for display. Be careful, though: overuse results in an anti-pattern.
But rendering an object for display is different from limiting hits against the database. As Randolph points out, if your intention is the latter, then use one of the existing deferred loading patterns, or better yet, use an ORM.
Take a look at the registry pattern, you can use it to find objects and also to better manage these objects, like keeping them in a cache.

Why LINQ to Entities won't let me initialize just some properties of an Entity?

So I've started to add Entity Framework 4 into a legacy web application (ASP.NET WebForms).
As a start I have auto-generated some entities from the database. Also I want to apply Repository Pattern.
There is an entity called Visitor and its repository VisitorRepository
In VisitorRepository I have the following method:
public IEnumerable<Visitor> GetActiveVisitors()
{
var visitors =
from v in _context.Visitors
where v.IsActive
select new Visitor
{
VisitorID = v.VisitorID,
EmailAddress = v.EmailAddress,
RegisterDate = v.RegisterDate,
Company = v.Company,
Position = v.Position,
FirstName = v.FirstName,
LastName = v.LastName
};
return visitors.ToList();
}
Please note that Visitor has more properties than those, I just don't want to get everything because there are some heavy TEXT fields.
That List is then bound to a repeater and when trying to do <%# Eval('EmailAddress') #%> it throws the following exception.
The entity or complex type 'Model.Visitor' cannot be constructed in a LINQ to Entities query.
A) Why is this happening? How I can workaround this? Do I need to select an anonymous type and then use that to partially initialize my entities??? I don't want to make a SELECT * because there are some heavy TEXT columns I don't need here
B) Why every example I've seen makes use of 'select new' (anonymous object) instead of initializing a known type? Anonymous types are useless unless you are retrieving the data and showing it in the same layer. As far as I know anonymous types cannot be returned from methods? So what's the real point of them???
Thank you all
a) It's happening because Visitor is an entity. You could say the following with the understanding that you won't be able to update the database via the resulting objects outside the data context in the repository:
var visitors =
from v in _context.Visitors
where v.IsActive
select v;
b) I don't know what example you are looking at but you are right to say that passing a collection of anonymous types from a repository in the data layer to the GUI isn't what you want. You can either use self-tracking entities or data transfer objects (DTOs). This MSDN article explains your options in detail.

Adding behavior to LINQ to Entities models

What's the preferred approach when using L2E to add behavior to the objects in the data model?
Having a wrapper class that implements the behavior you need with only the data you need
using (var dbh = new ffEntities())
{
var query = from feed in dbh.feeds select
new FFFeed(feed.name, new Uri(feed.uri), feed.refresh);
return query.ToList();
}
//Later in a separate place, not even in the same class
foreach (FFeed feed in feedList) { feed.doX(); }
Using directly the data model instances and have a method that operates over the IEnumerable of those instances
using (var dbh = new ffEntities())
{
var query = from feed in dbh.feeds select feed;
return query.ToList();
}
//Later in a separate place, not even in the same class
foreach (feeds feed in feedList) { doX(feed); }
Using extension methods on the data model class so it ends up having the extra methods the wrapper would have.
public static class dataModelExtensions {
public static void doX(this feeds source) {
//do X
}
}
//Later in a separate place, not even in the same class
foreach (feeds feed in feedList) { feed.doX(); }
Which one is best? I tend to favor the last approach as it's clean, doesn't interfere with the CRUD facilities (i can just use it to insert/update/delete directly, no need to wrap things back), but I wonder if there's a downside I haven't seen.
Is there a fourth approach? I fail at grasping LINQ's philosophy a bit, especially regarding LINQ to Entities.
The Entity classes are partial classes as far as i know, so you can add another file extending them directly using the partial keyword.
Else, i usually have a wrapper class, i.e. my ViewModel (i'm using WPF with MVVM). I also have some generic Helper classes with fluent interfaces that i use to add specific query filters to my ViewModel.
I think it's a mistake to put behaviors on entity types at all.
The Entity Framework is based around the Entity Data Model, described by one of its architects as "very close to the object data model of .NET, modulo the behaviors." Put another way, your entity model is designed to map relational data into object space, but it should not be extended with methods. Save your methods for business types.
Unlike some other ORMs, you are not stuck with whatever object type comes out of the black box. You can project to nearly any type with LINQ, even if it is shaped differently than your entity types. So use entity types for mapping only, not for business code, data transfer, or presentation models.
Entity types are declared partial when code is generated. This leads some developers to attempt to extend them into business types. This is a mistake. Indeed, it is rarely a good idea to extend entity types. The properties created within your entity model can be queried in LINQ to Entities; properties or methods you add to the partial class cannot be included in a query.
Consider these examples of a business method:
public Decimal CalculateEarnings(Guid id)
{
var timeRecord = (from tr in Context.TimeRecords
.Include(“Employee.Person”)
.Include(“Job.Steps”)
.Include(“TheWorld.And.ItsDog”)
where tr.Id = id
select tr).First();
// Calculate has deep knowledge of entity model
return EarningsHelpers.Calculate(timeRecord);
}
What's wrong with this method? The generated SQL is going to be ferociously complex, because we have asked the Entity Framework to materialize instances of entire objects merely to get at the minority of properties required by the Calculate method. The code is also fragile. Changing the model will not only break the eager loading (via the Include calls), but will also break the Calculate method.
The Single Responsibility Principle states that a class should have only one reason to change. In the example shown on the screen, the EarningsHelpers type has the responsibility both of actually calculating earnings and of keeping up-to-date with changes to the entity model. The first responsibility seems correct, the second doesn't sound right. Let's see if we can fix that.
public Decimal CalculateEarnings(Guid id)
{
var timeData = from tr in Context.TimeRecords
where tr.Id = id
select new EarningsCalculationContext
{
Salary = tr.Employee.Salary,
StepRates = from s in tr.Job.Steps
select s.Rate,
TotalHours = tr.Stop – tr.Start
}.First();
// Calculate has no knowledge of entity model
return EarningsHelpers.Calculate(timeData);
}
In the next example, I have rewritten the LINQ query to pick out only the bits of information required by the Calculate method, and project that information onto a type which rolls up the arguments for the Calculate method. If writing a new type just to pass arguments to a method seemed like too much work, I could have also projected onto an anonymous type, and passed Salary, StepRates, and TotalHours as individual arguments. But either way, we have fixed the dependency of EarningsHelpers on the entity model, and as a free bonus we've gotten more efficient SQL, as well.
You might look at this code and wonder what would happen if the Job property of TimeRecord where nullable. Wouldn't I get a null reference exception?
No, I would not. This code will not be compiled and executed as IL; it will be translated to SQL. LINQ to Entities coalesces null references. In the example query shown on the screen, StepRates would simply return null if Job was null. You can think of this as being identical to lazy loading, except without the extra database queries. The code says, "If there is a job, then load the rates from its steps."
An additional benefit of this kind of architecture is that it makes unit testing of the Web assembly very easy. Unit tests should not access a database, generally speaking (put another way, tests which do access a database are integration tests rather than unit tests). It's quite easy to write a mock repository which returns arrays of objects as Queryables rather than actually going to the Entity Framework.

Categories

Resources