I have a Branch table that contains:
company_id, is_deleted, branch_id, branch_name,开发者_JAVA技巧 branch_codecompany_id - used in order to determine which company owns the branch.
is_deleted - rows where is_deleted=true are logically deleted and I don't want to return them in my queries.I have to map thos fields to class Branch. Class Branch have the following members:
BranchId, BranchName, BranchCodeShould I add IsDeleted member in order to map the is_deleted field? Can I filter rows with is_deleted=true if I will not map this field?
Should I add CompanyId member in order to map the company_id field? I have many tables with company_id field since it decide whice company own the row. Can I prevent adding CompanyId member when mapping those tables? When inserting, I need to supply CompanyId - I really prefer to supply it externaly and not from the Branch object.
So now you have a concrete example so we can continue in discussion from your previous question where I described some basic information about mapping to existing objects.
Should I add IsDeleted member in order to map the is_deleted field? Can I filter rows with is_deleted=true if I will not map this field?
It is possible. It's called conditional mapping where your is_delete
column will be used as a filter in the mapping. It has pros and cons:
Pros:
- The filter is applied every time you query the entity set including a lazy loading and an eager loading. You will never get an entity with
is_deleted = 1
.
Cons:
- You can't map
is_deleted
as a property in the entity. This is one global disadvantage for all columns used to support conditional mapping, table per hierarchy inheritance and independent associations - they can't be exposed as properties. So how would you soft delete your entity if you don't have the column exposed and you can't set it in the application? The only solution for this is stored procedure mapped to delete operation for your entity - btw. it is probably the best solution if you want to do soft / logical deletes because otherwise accidental call ofDeleteObject
on the context or a set will do hard delete in the database. - You can't map multiple conditional entities to the same table. It means you can't have conditionally mapped both undeleted and deleted entity. This can be handled by table per hierarchy inheritance.
Btw. as I know this is not available in DbContext API (EF 4.1).
Should I add CompanyId member in order to map the company_id field? I have many tables with company_id field since it decide which company own the row. Can I prevent adding CompanyId member when mapping those tables? When inserting, I need to supply CompanyId - I really prefer to supply it externaly and not from the Branch object.
Do you have a relation between the company table and the branch table in your database? In such case your Branch
entity must use either independent or foreign key association with the Company
entity. Association by default creates navigation property on both related entities so your Company entity will have collection of related Branches and your Branch will have a reference to the Company it belongs to. Navigation properties are the main way how to create relations in the object world. So if you want the Branch to belong to any Company you will either assign the Company to the property in the Branch or add the Branch to the collection of branches in the Company. That is the theory - it is little bit more complex with EF when using detached objects.
To avoid some problems EFv4 introduced foreign key association where dependent entity doesn't have only navigation property but also foreign key property (your country_id). You can create relation simply by assigning this property with the id of related Country.
I have already answered separate question describing differences between Independent and Foreign key associations.
Conclusion: You must use either navigation property or foreign key property to create relation between object - both these artifacts are mapped in the entity.
Now example which will also show some details you asked me yesterday. This example shows following features:
- Conditional mapping (When is_deleted = 0 in mapping details)
- Independent association (I have also already described how to change Independent association to Foreign key association). If you are creating the model from existing database you can check Include foreign key columns in the model in Update wizard and it will use foreign key associations instead of independent associations in the whole model.
- Navigation properties on both sides of the relation
- Renaming properties in conceptual model (check mapping details where nice names are mapped to database names)
- Changing accessibility of the Id property setter. I already answered similar question where this was required with POCO T4 template but same must be done for custom business objects.
- Support for lazy loading - check virtual keyword used in business object's code for navigation properties.
- Support for tracking proxies - check virtual keyword used in business object's code for scalar properties.
Related mapped business objects will look like:
public class Branch
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual string Code { get; set; }
public virtual Company Company { get; set; }
}
public class Company
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Branch> Branches { get; set; }
}
And context using these custom business objects can look like:
public class Context : ObjectContext
{
public Context()
:base ("name=ModelContainer")
{
Companies = CreateObjectSet<Company>();
Branches = CreateObjectSet<Branch>();
ContextOptions.LazyLoadingEnabled = true;
ContextOptions.ProxyCreationEnabled = true;
}
public ObjectSet<Company> Companies { get; private set; }
public ObjectSet<Branch> Branches { get; private set; }
}
No, you're going to need the field visible if you want to do something like filter on it, unless you use Stored Procedures.
I don't really understand this one. Why would you NOT want company_id visible if you need to use it when inserting? It's not going to hurt anything if it's there. :)
精彩评论