问题
Linq to SQL, C#.
I have 3 layers: DAL,BL,Application. I want to build functions of search in the BL for each table so those functions get as a parameter 'where' expresstion from the Application layer. The advantage in this approach is one function for each table so the client can search in a free and dynamic way insted of givving him 5 (for example) ways; restrict his search.
For that I need to give my Application layer a DLL of my DAL layer. Doing that is not a good approach to solve the problem (givving the user to build his search dynamicly insted of restrict him with a builded up search functions). If the Application layer have a DLL to my DAL layer, the Aplication layer can declare a ContextObject and do bad things for my Data-Base.
What can I do for solving this problem?
Thanks alot, Stav Alfi.
Update 1:
As you know, the Linq to Sql build a class to each table. I dont want to expose the DAL DLL to the Application layer so I can not use Linq to Sql's classes in the Application layer. The solution I found is to build classes that look the same to the Linq to Sql's classes, so the Application layer can use them. The BL layer is resposnibol for convring those classes. From the fact that the Application layer does not use Linq to Sql's classes, I can't give to the Application layer a IQueryable (Any result of Any function of the BL layer is converted to the Application layer's classes).
Update 2:
The Linq to Sql have LinqClientDB.designer.cs and it Build up those classes
[global::System.Data.Linq.Mapping.DatabaseAttribute(Name="ClientDB")]
public partial class LinqClientDBDataContext : System.Data.Linq.DataContext
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Clients")]
public partial class Client : INotifyPropertyChanging, INotifyPropertyChanged
If I expose the DAL layer to the Application layer, the Application layer can have access to the LinqClientDBDataContext class. this is not a good approach. So in the BL layer I convert the DAL.Client class to a BL.Client class but then I cant have a dynamic search on the Client's table. What can I do?
回答1:
Exposing IQueryable<T>
through your BL does not expose your DAL. Since you want to encapsulate the database entities in separate classes for the application layer, you can still do this, although the application will be more limited in the types of queries it can run.
// DAL
public class Entity { ... }
// BL
public class EntityInfo : Entity { ... }
...
public IQueryable<EntityInfo> GetEntities()
{
return from e in dbContext.Entities
select new EntityInfo
{
// populate your application layer object
}
}
Here's an alternative way of coding it that provides the same result
public Expression<Func<Entity, EntityInfo>> materializeEntityInfo =
e => new EntityInfo { .. };
public IQueryable<EntityInfo> GetEntities()
{
return dbContext.Entities.Select(materializeEntityInfo);
}
回答2:
You can make the context class internal
while the entity classes are public
.
This would allow you to create service classes in your DAL that return entity classes (as IEnumerable
s) from a context that is not exposed to the client.
Although this is true, it is often advisable (as p.s.w.g said) to have DTO or view model objects exposed to the client (or application layer) because is abstracts the DAL.
来源:https://stackoverflow.com/questions/15721627/linq-to-sql-making-a-dynamic-search-for-the-application-layer-without-exposing