Modeling Localized Data in Entity Framework Code First - c#

I'm trying to create a domain model that supports localization. I've looked at some SO questions that were asked before but I did not really like the solutions proposed. For example, in this question I think it's an overkill to create an additional entity for each and every entity that should support localized data. I'd rather have the localized data for all of my entities be in one entity whose sole purpose is to hold the localized data.
My proposed solution is as follows:
Create a LocalizedEntity class from which all of the entities that should support localization would inherit.
Create a LocalizedData entity which will basically hold the actual localized values by culture.
UPDATE:
public class LocalizedEntity
{
public String Code { get; set; }
}
public enum ResourceType
{
CityName,
CityDescription,
StreetName,
AreaName
//others...
}
public class LocalizedData
{
public Int32 Id { get; set; }
public String Code { get; set; }
public ResourceType Type { get; set; }
public Int32 CultureId { get; set; }
public String Value { get; set; }
}
public class City : LocalizedEntity
{
public Int32 Id { get; set; }
public virtual ICollection<Area> Areas { get; set; }
//others
}
Accordingly, the business layer will fetch the localized entity, and then go and get its localized value from the LocalizedData entity by Code and ResourceType. And of course, in order to avoid many round-trips to the database, some caching could be appropriate.
Your thoughts?

What you're modeling is EAV (entity-attribute-value) storage. Very soon your "resource type" enum will overflow into unmanageable state. To add injury to insult, that's pretty uneffective in terms of database structure.
If you want localization that's still maintainable in terms of db usage of code readability, you should localize entities, not properties, which means that each row in database should hold entity id, language id and data for that entity in that language.

Related

Status Entities in .NET Core Entity Framework - suggested implementation

I am new to full stack software development, and I have an assignment to create a simple full stack web app in .NET Core, Entity Framework Core (when it comes to the back-end part), which would store some employee data. Now, let's say I have an Employee entity. We also need to implement the Employee's position in some way (an employee can have the position of a back-end developer, front-end developer, project manager etc.). That's why I have also created this EmployeePosition class, so that there is an EmployeePosition property in Employee. I also have other similar status enitities like the EmployeePosition in the app.
EmployeePosition would then be seeded to a separate table in the database, and thus it can be applicable to any company that "would use" this app (just use different seed data). I will use a legacy database for seeding.
Now it seems that this would work, but it also seems a bit too crude for me, because whenever I would need to do an operation with the status in the repository, I would have the use the magic Id number of the status, or hardcode the status Name property somewhere in a method (if I don't have a smarter workaround for the given operation), for instance "Switch(Position.Name) case "front-end": do stuff" etc.
Could I maybe get a suggestion or direction on how to implement this better, am I on a good track here?
Would it be better to actually use enums as data types inside of EmployeePosition, any suggestions on how to implement that? Considering that I have to use the legacy database for seeding, I would have to somehow create my enums out of the legacy file.
public class Employee
{
[Key]
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string Image { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Phone { get; set; }
[Required]
public EmployeePosition Position { get; set; }
public class EmployeePosition
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
What you can do is create an Enum for employee positions.
public enum EmployeePosition
{
Backend = 0,
Frontend = 1,
DBA = 2,
}
And your employee entity
public class Employee
{
[Key]
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string Image { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Phone { get; set; }
[Required]
public EmployeePosition Position { get; set; }
}
Then you can use
If (Employee.Position == EmployeePosition.Backend)
{
// your logic.
}
You have conflicting requirements unfortunately. You say that your program is "status-agnostic":
EmployeePosition would then be seeded to a separate table in the database, and thus it can be applicable to any company that "would use" this app (just use different seed data).
And yet, it's really not:
Because whenever I would need to do an operation with the status in the repository, I would have the use the magic Id number of the status, or hardcode the status Name property somewhere in a method (if I don't have a smarter workaround for the given operation), for instance "Switch(Position.Name) case "front-end": do stuff" etc.
So one of those requirements has to "win". Either your code knows what the different statuses are (and so different seed data wouldn't work) or it doesn't.
If the first requirement is more important:
Keep your code as it is, you have a perfectly reasonable model for N number of statuses where they aren't known ahead of time, nor is any logic specific to a given entry
If the second requirement is more important:
Switch to an enum. You don't want magic numbers or strings floating around in your code. As you mention, you'll need to map each existing data row into one of the predefined enum members.

Exposing EF6 model subsets via WebAPI

For example, I have a EF6 model like this:
class User
{
public int Id { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public virtual ICollection<ProfileProperty> Properties { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
class Book
{
public int Id { get; set }
public int Name { get; set }
public DateTime CreationDate { get; set }
public long Size { get; set }
public string ContentPath { get; set }
}
And now I want to create a WebAPI that allows to:
Create a new user
Update user's name
Modify the list of user's books
However, here are a few tricks to it which don't let me use tutorials right off:
Some fields are either irrelevant or confidential and must not be exposed via WebAPI, for example: User.Id, User.Properties, and nested User.Books[x].ContentPath.
Only a small subset of fields is editable (in the example, User.Name).
Only a small subset of operations (CRUD) is available, therefore it's not a REST service.
The first thing that comes to mind is create extra classes for each exposed model. However, maintaining them and writing code that converts data from database models to those WebAPI-friendly classes and back is too bothersome. Is there a more simple and automated way?
The ideal approach would be one which requires writing as little redundant code as possible. Maybe there is a set of attributes to mark fields with?
You're right in thinking you should create more classes. For each exposed action (change name, create user, etc...) you should create a ViewModel that exposes only the fields you need.
public class ChangeUserNameViewModel
{
public int UserId { get; set; }
public string NewName { get; set; }
}
It's easy to convert your view model to your domain model and back again using something like AutoMapper.

Class linking best practices in C#

First off, EF is not an option for our development environment so please no "just use EF" answers ...
I think this is a pretty standard dilemma so I'm sure there must be a way that most Pros do it that I just have not stumbled across ... so I'm out here hoping y'all can show me what it is.
Let's say you have the following database tables:
tblCompanies
ID
NAME
tblDepartments
ID
COMPANY_ID
NAME
tblEmployees
ID
DEPARTMENT_ID
FIRSTNAME
LASTNAME
... what's the best way to represent this in Classes within your code?
I assume the best way is like this:
public class Company
{
public int ID { get; set; }
public string Name { get; set; }
public List<Department> Departments { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public List<Employee> Employees { get; set; }
}
public class Employee
{
public int ID { get; set; }
public string FirstName { get; set;}
public string LastName { get; set; }
}
I believe that to the be the "OOP Proper approach" to this. However, what seems to always happens is something like this:
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public int CompanyID { get; set; }
public List<Employee> Employees { get; set; }
}
... mainly because when you pull just a Department from the database you are only going to have Company ID, not all the other attributes needed to fully populated an instance of the Company class.
(I've used a pretty vanilla example here but the one I'm actually tackling in my current project has 3 fields that it uses to link the data together so the thought of having the same 3 fields in several classes seems wrong to me)
Is there a Best Practice for these scenarios? As much as I don't like the thought of storing the same data in multiple classes just out of laziness, I also don't like returning an instance of a class with just one of its fields populated because that's all I had at the time.
This is a common problem, and one that ORMs try to solve. To be sure it isn't an easy one depending on what your wants are and what your constraints are.
There are only two fundamental options to keep one copy of the information. Lazily load the data as requested or load it all to begin with (Greedy load). Otherwise you have to duplicate the data.
With lazy loading you basically set things up such that when navigating into a property you make a call to the database and grab the information needed to load the entity representing the property you are accessing. The tricky part to watch with this is the SELECT N + 1 problem. You experience this problem when you end up iterating a set of parent entities and trigger lazy loads on every child entity, thus resulting in N+1 calls to the database to load a set of entities (1) and their children (N).
Greedy loading basically says load everything you need to start with. ORMs (where they work) are nice because they take care of many of the details via LINQ and create solutions that can be performant and maintainable usually along with the ability of allowing you to manipulate the usage of Greedy and Lazy Loading.
Another important gotcha is many to many relationships. You need to make sure not to have circular initialization, and get all the baggage of circular dependencies. There are surely many more I have missed.
In my humble opinion I am not so sure there is a best practice as much as there are practices with some of them bad - nothing is perfect. You can:
Start rolling your own object relational mapper allowing you to get rid of the duplicate ID
Use a lighter ORM framework to handle some of this allowing you to get rid of the duplicate ID
Create specialized queries to load aggregations of data allowing you to get rid of the duplicate ID (* cough * DDD)
Just keep the duplication of the ID like you mention above and not worry about creating an explicit relational model in your domain.
This one is on you to choose what is best based on your constraints. This is a deep topic and my experience is limited...so take what I am saying with alot of salt.
I don't think there's a "best practices" manual for this kind of things, and surely it depends on how your classes are going to be used. But in my personal experience, I have ended up following this approach:
public class Company
{
public int ID { get; set; }
public string Name { get; set; }
public IEnumerable<Department> GetDepartments()
{
// Get departments here
}
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
protected int CompanyID { get; set; }
private Company _Company;
public Company Company
{
get
{
// Get company here
}
}
public IEnumberable<Employee> GetEmployees()
{
// Get employees here
}
}
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
protected int DepartmentID { get; set; }
private Department _Department;
public Department Department
{
get
{
// Get department here
}
}
public IEnumberable<Employee> GetEmployees()
{
// Get employees here
}
}
In some cases I have exposed some of the "navigation" properties of my classes as public (like CompanyID and DepartmentID) to prevent the instantiation of a new class to get a value that has been loaded already.
As others have noted, you could also simulate "lazy loading", but this will require some extra effort from your part.
I would think it depends on requirements. Do you need to traverse upward (get company from department, department from employee, etc). If you do, then it is best that you provide a means of doing that. Ideally that would be something like a Company or Department property, of course you wouldn't want to get data you don't really need, so you'd likely keep a private company id and have a public getCompany function which queries for the data.
I believe that this is not a really OOP question, in your case you just have an database model (database representation in classes) which does not contain any logic and all the classes are used as structs, and this is a right way to map your database to classes - structs. So in your next module which will represent the logic of your program you have to map your database module to the real classes which will contain the logic (I mean methods which will implement it) of course if you really need them. So in my opinion the OO question should be in the logic part of your application. On the other hand you could take a look on nhibernate and how the mapping done in there it will give you a hint for the bes database model implementation.
I believe this is what your classes would look like in NHibernate:
public class Company
{
public int ID { get; set; }
public string Name { get; set; }
public IList<Department> Departments { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public Company Company { get; set; }
public IList<Employee> Employees { get; set; }
}
public class Employee
{
public int ID { get; set; }
public string FirstName { get; set;}
public string LastName { get; set; }
public Department Department { get; set; }
}
Note that there is a way to navigate from Employee to Department and from Department to Company (in addition to what you already specified).
NHibernate has all kinds of features to make that just work. And it works very, very well. The main trick is run-time proxy objects to allow for lazy loading. Also, NHibernate supports a lot of different ways to eager and lazy load just exactly how you want to do it.
Sure, you can get these same features without NHibernate or a similar ORM, but why wouldn't use just use a feature rich mainstream techology instead of hand coding your own feature poor custom ORM?
There is another option. Create a 'DataController' class which handles the loading and 'memoization' of your objects. The dataController maintains a dictionary of [CompanyIDs, Company objects] and [DepartmentIDs, Department objects]. When you load a new Department or Company, you keep a record in this DataController dictionary. Then when you instantiate a new Department or Employee you can either directly set the references to the parent objects OR you can use a Lazy[Company/Department] object and set it using a lambda (in the constructor) which will maintain the scope of the DataController without it being referenced directly inside the objects. One thing I forgot to mention, you can also place logic in the getter / get method for the Dictionaries that queries the database if a particular ID is not found. Using all of this together allows your Classes (Models) to be very clean while still being fairly flexible as to when / how their data is loaded.

How to represent dynamic enum-like fields / properties in an Entity Framework 4.1 model?

I'm trying to whip up a POC of a system which allows you to create and modify enumerations that are eventually used in an application using the front-end. Something like dynamic enums.
For example, in a hypothetical bug tracker application, we can have a status enum that could have values of open,accepted and closed. All these enums (and their corresponding values) can be changed in real-time via the UI, so it is possible for an admin to come up with a new reassigned value for example (through an Admin page, most probably) somewhere down the application's lifetime. It would also be possible to create new enums as well, which in turn have their own values (for example, a complexity enum).
The way I'm currently envisioning it is that I'll have an Enumeration class, which has a 1:* referential with an EnumerationValue class.
public class Enumeration {
public string Name { get; set; }
public ICollection<EnumerationValue> Values { get; set; }
}
public class EnumerationValue {
public string Name { get; set; }
public string Description { get; set; }
}
That's the easy part. When I get to creating the entity that actually uses these dynamic enums, I hit a snag.
Let's say I'm creating the BugRecord entity, which consequently has a Status property. Following the logic above, I'd have to write it along the lines of:
public class BugRecord {
public EnumerationValue Status { get; set; }
}
But given that I could have lots of different Enumerations (and EnumerationValues), is there a way for me to restrict BugRecord.Status values to only EnumerationValues in the status Enumeration? If not how would you recommend I tackle a problem of this kind?
Create a third Entity/JoinTable EnumerationChoice and use it to map the BugRecord to the EnumerationValue
public class EnumerationChoice {
public Enumeration EnumerationCategory { get; set; }
public EnumerationValue Value { get; set; }
}
BugRecord now becomes:
public class BugRecord {
public EnumerationChoice BugType { get; set; }
public EnumerationChoice Status { get; set; }
}
The data would now look like:
BugRecord:
EnumerationChoice:
-BugType
-BugTypeValue1
EnumerationChoice:
-Status
-Open
This way, when you try to populate the EnumerationChoice, you can reference the EnumerationCategory to get the valid EnumerationValues assigned to it.

Entities Architecture

Using VS2010, .NET4.0, MVC3, EF4.1 Code-First
I have this POCO entities:
public class XBLContent
{
[Key]
[StringLength(36, ErrorMessage="Must have 36 characters")]
[Required(ErrorMessage="Must have a unique GUID")]
public string GUID { get; set; }
public int Price { get; set; }
public float FileSize { get; set; }
public virtual ICollection<XBLRegionalContent> RegionalInfo { get; set; }
public string RelatedGameId { get; set; }
[ForeignKey("RelatedGameId")]
public virtual XBLContent RelatedGame { get; set; }
}
public class XBLRegionalContent
{
[Key, Column(Order = 0)]
public string ContentId { get; set; }
[ForeignKey("ContentId")]
public virtual XBLContent Content { get; set; }
[Key, Column(Order = 1)]
public string RegionId { get; set; }
[ForeignKey("RegionId")]
public virtual XBLRegion Region { get; set; }
public string Name { get; set; }
}
public class XBLRegion
{
[Key]
[StringLength(5, ErrorMessage="ID must have 5 characters")]
[Required]
[RegularExpression(#"[a-z|A-Z]{2}-[A-Z|a-z]{2}")]
public string ID { get; set; }
public string Country { get; set; }
public string Language { get; set; }
}
Relationships:
One XBLContent has many XBLRegionalContent;
One XBLContent can be related to another XBLContent(most of them are not);
One XBLRegionalContent has one XBLContent and one XBLRegion;
One XBLRegion has many XBLRegionalContent;
The Context objetc is really simple:
public class XBLContentContext : DbContext
{
public DbSet<XBLContent> XBLContents { get; set; }
public DbSet<XBLRegionalContent> XBLRegionalInfos { get; set; }
public DbSet<XBLRegion> XBLRegion { get; set; }
public XBLContentContext() : base("XBLToolsDB")
{
}
}
I'm using XBLContent as my main business object and maybe that is not the best idea. I think there is something wrong with the architecture I designed because I'm having trouble to send information to the View and filter, sort, etc.
Now, I'm using Telerik grid and when I try to sort by a navigation property field I get an error saying that "No property or field exist". Maybe I should not use XBLContent as my main business object, or create a ViewModel containing all needed fields and send it to the View. Or create one single entity that splits into two EF tables(I don't know if that is possible or how to achieve that).
I'm just padawan in .NET and need some Jedi Masters advice.
I need contents that can have multiple translations.
How to best achieve this goal?
this should fix your problem.
http://weblogs.asp.net/manavi/ A great resource for beginners and i can see you have used a lot of annotations ,so a little bit of fluent api would make your concepts stronger.
I'm assuming you're using the Telerik MVC Extensions here, but if you are using a different product please let me know and I'll re-answer accordingly :)
In regards to the Grid what kind of binding are you utilizing? If you are using regular server or ajax binding then you might run into some issues when binding to a navigational property, as by default these bindings only work with primitive (int, string etc.) types. However, there is such a thing as custom binding which allows you to take full control over paging/sorting/filtering. I believe this could account for why you are getting this error, as the automatic LINQ expressions cannot find the specific field you are looking for. Here are two demos (which have source code for both WebForms and Razor ViewEngines) that can help with setting up custom binding. It's just a little more work than the automatic binding, but should still work (note that these examples are using Razor):
Ajax Binding
Server Binding
The added benefit here is that you get to control everything on your own, which can be quite nice in somewhat more complex scenarios. If you're already using custom binding, and/or if the links there do not help let me know. It could also be helpful to have the code for the Telerik Grid.
I've resolved these kinds of issues by normalizing the results like:
from r in ctx.XBLContents
select new
{
r.Guid,
RelatedGuid = r.RelatedGame.Guid
};
Essentially creating an anonymous classes that is more denormalized has worked for me to work around these kinds of issues, where the results denormalizes those navigational properties too.
HTH.

Categories