Where to store a function that involves two entities? - c#

I have two tables in my database. Companies and Sites. Each Company has many Sites. The Sites table has has a foreign key of CompanyID.
I have a data layer class for each entity, one for the company, and one for the site.
I need to get the CompanyID by the SiteID and so I can write a method like this:
public Guid GetCompanyGuidBySiteGuid(Guid siteId) =>
_util.SelectGuid("SELECT s.CompanyID FROM pm.Site s WHERE s.SiteID = #SiteId", ("#SiteId", siteId));
Which data layer should I put this method in? The CompanyDataLayer, or the SiteDataLayer?
This is a specific question but also a general one. How does one make these kinds decisions in general when there are overlap between modules?

Related

Entity Framework Code First with Dynamics Navision Tables

I have a project where I need to design a code first entity system with an existing database. These existing tables in the database are not just any tables, they were being created by Microsoft's ERP tool "Dynamics Navision". The Navision tool holds different company information and creates different tables per company. Let's assume there are 3 types of tables;
TableX
TableY
TableZ
And also there are 3 different companies;
CompanyA
CompanyB
CompanyC
The tool created 9 different tables from above combinations. It simply duplicates all of the tables and adds a prefix with the company name to the table names. At the end, our database looks like this;
CompanyA$TableX
CompanyA$TableY
CompanyA$TableZ
CompanyB$TableX
CompanyB$TableY
CompanyB$TableZ
CompanyC$TableX
CompanyC$TableY
CompanyC$TableZ
What Did I do so far?
So as you can see, there is an opportunity to simplify this architecture at the Entity Framework side. To achieve this, I created 3 entity classes for TableA, TableB, TableC and at the run time, I let the user to choose a company and according to the chosen company, I reflected my entity class with a custom TableAttribute where the table name prefixed with the company name. I am not going to give details on how I achieved it right now(but you can find implementation details on this article: LINK) but so far so good and I have applied all of the previous steps successfully and I managed to be dynamic on table names with the chosen company. However, there is another problem.
What is my question?
The problem is, even though I managed to create a system where I can change the entity class' table name attribute at the runtime and access to the target companies tables, there were no guarantee that duplicated tables with different company name prefixes are sharing %100 same inner field architecture. For example, CompanyA$TableX can have 5 fields while CompanyB$TableX has 6 fields where the first 5 fields are the same with CompanyA$TableX's fields but the last 1 field is extra. Let's also visualize it;
CompanyA$TableX's table fields;
ID
Name
Surname
Adress
PhoneNumber
CompanyB$TableX's table fields;
ID
Name
Surname
Adress
PhoneNumber
EMail
As you see, the Email field is the extra however the table names are the same(TableX), only the company differs and in my system, they share the same entity class and the company name determined at the run time as I mentioned before.
So, I want to know about how can I achieve to be dynamic on this. How I can have only one entity class but be dynamic in the fields of this class according to the chosen company. I want to know if it is possible technically and if it is, how to implement it. Thanks in advance.
What you are saying about Nav is not true. It is not possible to create the same table in Nav that will have different structure per company. Even the modern extension architecture will not give you that kind of result.

Entity Framework 6 Make relation on behalf of ID or enum value

In my DB I have a relation between some tables that is relying on either an ID or an Enum value. Here is the structure:
Employee
ID
Name
RoleEnum (CEO, Leader, Developer)
Virtual list of Advantages
Advantages
ID
Description
EmployeeAdvantages
ID
AdvantagesID
EmployeeID (Nullable) *
RoleEnum (Nullable) *
*) only one of them will have a value for each row
The relation between Employee and Advantages can be either based on a direct relation based on EmployeeID and AdvantagesID or based on the RoleEnum.
So when I load a Employee with the EF then I would like the virtual list of advantages to be filled automatic, And this behaviour is also working when the relation is based on EmployeeID and AdvantagesID, BUT when it is based on RoleEnum it is of course not working out of the box, but isn't it possible to configure EF to handle that situation? So if the employee has a role of "CEO" it will load all the relations that is based on that in role in EmployeeAdvantages?
It is better from a relational modelling perspective that you separate Advantages of Employees from Advantages of Roles.
It is better to have a separate table like RoleAdvantages
This way you can make a relationship between Employee and RoleAdvantage based on the role of the employee and thus automatically load Advantages of that Role. You only then have to collect Advantages from both collections.
As far as I know, what you want is not possible. But you could create an extension for Employee where you manually load the EmployeeAdvantages that come through the RoleEnum. Basically you would do this in your extension method:
public static class EmployeeExtension
{
public static int VirtualListOfAdvantages(this Employee employee)
{
var repo = new EmployeeAdvantagesRepository();
var enumRoleAdvantages =
repo.GetAll().Where(ea => ea.RoleEnum == employee.RoleEnum).ToList();
enumRoleAdvantages.AddRange(employee.VirtualListOfAdvantages);
return enumRoleAdvantages;
}
}
(I don't know how your repository would look like, but I think you get the idea)
This is certainly not the solution you were looking for, but it's a valid and quite simple solution that should work well.
More about extension methods (and example taken from): How to: Implement and Call a Custom Extension Method

EntityFramework custom many to many without navigation property

I want to do many-to-many relation between these objects:
class Flyer {
Guid Id;
virtual ICollection<Address> Stores;
}
And:
class Address {
Guid Id;
}
Of course these models are simplified.
And I do not want a navigation property to Flyer inside Address because Address is in relation with other objects too. It is possible?
Fluent API only
How are you identifying what the address belongs to if it can belong to multiple different tables? Do you have a Join table? Like a AddressToFlyer Table that establishes the relationship between the two tables?
When I have complex queries that need to take place like this where one table can be used by many tables, I create join tables and typically create views that handle the joins and give me the data what I want so I can just do a select in Entity Framework and not worry about the Navigational property, then implement said view in Entity framework like you would a regular table.

Many-to-Many relationship in WPF with EF and SQLite

I'm following this tutorial in order to implement a local database (using SQLite) for my WPF application.
Everything works as it should, although I have a logical problem I don't know how to solve using this approach. I'll simplify it below.
Database-wise, I have 2 tables (A,B) which share a many-to-many relationship, and thus require a JOIN table as well (ABJoin).
In my actual code however, I'd like to use only 2 models: A and B, which each having a list of the other type. Like this:
public class A {
// ...fields
List<B> bList;
}
public class B {
// ...fields
List<A> aList;
}
How can it be implemented in EF+SQLite?
Searching online, I have found some solutions, but nothing that applies to SQLite, so I was not sure how they'd work.
Configure Many-to-Many Relationships in Code-First
If you are using many to many join table then your each class should have a list of the join table.
It cannot work the way you are thinking.
Are you sure that it is a good idea not to have a third entity?
Lets say your two entities were DepartmentStore and Product, a typical example for an n:n relationship. A department store can sell many products and a product may be available in many departments stores. This results in a third entity which connects the two above, in the example above this would something like ProductAvailability.
If you think about it more careful, then you might realize that the new connecting entity might have properties of its own. In my example this might be NumberOfProducts, will states the available quantity of a product in a certain department store.
In my experience, it is quite common for the connecting entity to have a real value that goes beyond just connecting two other entities.
I also took a look at you example which it about Album and Artist entities.
Do you want to make a data model where an Album can be created by more than one Artist?
Entity Framework doesn't have automatic many-to-many mapping.
Instead of this, you can map A and B to intermediate table as one-to-many.
If you are not obliged to use only EF, I suggest to try NHibernate ORM instead.
It has convenient many-to-many mapping and generally more powerful.

Repository pattern and localized lookup tables

I am trying to grabs the idea of the pattern repository and trying to get it implemented in database structures I've already set up in the past. I'm now trying to get the best practice to work with my lookup tables. I've created a test project to play around and this is my database model:
You can see that I have three tables for the lookups: Lookup, Language and LookupLanguage. Language table simply contains the languages.
Lookup tables holds the different types used throughout the models.
And LookupLanguage links the both tables together:
I've created anew project with all the models 1 to 1 to the database tables:
I also created a generic repository and a generic CrudService interface:
public interface ICrudService<T> where T : IsActiveEntity, new()
{
int Create(T item);
void Save();
void Delete(int id);
T Get(int id);
IEnumerable<T> GetAll();
IEnumerable<T> Where(Expression<Func<T, bool>> func, bool showDeleted = false);
void Restore(int id);
}
Now, according to the following post: When implementing the repository pattern should lookup value / tables get their own Repository? , the repository should hide the underlying database layer. So I think I need a new implementation of a service and/or repository to get the lookups, but then, where do I have to tell in which language I need to have the lookup?
Let's take the status (new, accepted, refused) from the company as an example.
The company model is as follow:
public partial class Company : IsActiveEntity
{
[Required]
[MaxLength(50)]
public string CompanyName { get; set; }
public System.Guid StatusGuid { get; set; }
[ForeignKey("StatusGuid")]
public virtual Lookup Status { get; set; }
}
I guess I don't need to have a separate implementation of a repository?
But I need a separate implementation CompanyService.
interface ICompanyService : ICrudService<Company>
{
IQueryable<LookupLanguage> GetStatuses(Guid languageguid);
LookupLanguage GetStatus(Guid statusguid, Guid languageguid);
}
Is this the correct approach, or do I miss something here?
Creating a Generic LookupRepository in your case in a better option because of your table schema and maintainence perspective.
I'm not sure whether you are using both Service Locator and Repository pattern or just Repository because of the name ICompanyService. But regardless, I agree that Repositories should not represent tables 1-1 always but they do most of the times.
The SO link you provided has a different table structure than yours. You have a generic lookup table vs the link has a separate table for each lookup. In the case where you have separate tables it makes sense to have the lookup repository method go with the entity repository since you will have a separate code to fetch the data for each lookup(as they have separate tables with different schema).
But in you case you have a single table that stores all the lookup types for each language and it makes sense to have a single LookupRepository that returns all the various types of lookups based on Language and LookupType. If you create each lookup method in separate entity repositories (like GetStatuses in CompanyRepository and GetStatuses in ContactRepository) you will have to repeat the logic in the method for each repository.
Think if you change the schema of the lookup table (say add a column) and you want to test all places the lookups are used it will be nightmare if you have lookup methods all over the place and pretty easy if you have one method in LookupRepository.
interface ILookupService : ICrudService<Lookup>
{
IQueryable<Lookup> GetStatuses(Guid languageguid, LookupType lookupType);
Lookup GetStatus(Guid statusguid, Guid languageguid, LookupType lookupType);
}
As regards your question, "Is this the correct approach" - this entirely depends on your specific needs.
What you have done doesn't seem to have any real issues. You have implemented the repository pattern using generics which is great. You are using interfaces for your repositories which allows for easier unit testing, also great!
One of your tags seems to indicate you are interested in the Entity Framework. You do not seem to be using that. The Entity Framework would simplify your code by creating the boiler plate classes for you. You can still use your repository pattern code with the classes created by the Entity Framework.
It seems that you are confusing the idea of a service and a repository. A repository is a general object which allows you to get data from a store without caring about the implementation. In your example, ICompanyService is a repository.
It is really controversial topic and there are different approaches to this problem. In our data logic we are not using repository pattern because we do not want to abstract most of the benefits of Entity Framework. Instead, we pass the context to the business logic which is already a combination of UoW / Repository pattern. Your approach is okay if you are going this way on all of your company services. However what I have seen so far, putting methods to the related services by their return values is the best approach to remind where they are. For instance if you want to get the company lookup, create a ILookupService and put GetLookUpsByCompany(int companyId) method to retrieve the company lookups.
I would argue with the linked response. Repositories ARE linked to database entities, considering the Entity Framework itself as a uow/repository implementation is a best example. On the other hand, services are for domain concerns and if there is a mismatch between your database entities and domain entities (you have two separate layers), services can help to glue the two.
In your specific case, you have repositories although you call them services. And you need a repository per database entity, that's just easier to implement and maintain. And also it helps to answer your question: yes, you need the extra repository for the linking table.
A small suggestion. You seem to have a generic query function that only accepts where clauses
IEnumerable<T> Where(Expression<Func<T, bool>> func, bool showDeleted = false);
If you already follow this route that allows arbitrary filtering expressions (which itself is a little arguable as someone will point out that you can' possibly guarantee that all technically possible filters can be executed by the database engine), why don't you allow all possible queries, including ordering, paging, etc:
IQueryable<T> Query { get; }
This is as easy to implement as your version (you just expose the dbset) but allows clients to perform more complicated queries, with the same possible concern that such contract is possibly too broad.
Localization is a presentation layer thing. The lower layers of your application should bother with it as little as possible.
I see two different kind of lookups: translations of coded concepts (Mr/Miss/Mrs) and translations of entity properties (company name maybe, or job titles or product names).
Coded concepts
I would not use lookup tables for coded concepts. There is no need to bother the lower layers at all with this. You will only need to translate them once for the entire application and create simple resource files that contain the translations.
But if you do wish to keep the translations in the database, a separate lookup repository for the codes or even per code system will sort of replace the resource file and serve you fine.
Entity properties
I can imagine different/nastier localization issues when certain entities have one or more properties that get translated in different languages. Then, the translation becomes part of the entity. I'd want the repository to cough up entity objects that contain all translations of the description, in a dictionary or so. Cause the business layer should not worry about language when querying, caching and updating relations. It should not ask the company repository for the Dutch version of company X. It should simply ask for company X and be served a Company object that contains its name in Dutch, English and French.
I've one more remark about the actual database implementation:
I think the lookup tables are distracting from the actual entities, to the point where you have forgotten to create a relation between person and person company. ;) I'd suggest putting all translations of entity properties in a single XML type column instead.
This illustrates why the repository should handle entities plus translations. If you were to make this storage layer level implementation change at some point, i.e. go from lookup tables to xml columns, the repository interfaces should remain the same.

Categories

Resources