How the Application layer will be able to dynamicl

2019-08-25 16:01发布

问题:

C#, LINQ to SQL

Some advice me to open new topic insteed that topic becouse there is no solution for my problem. Now I will need your help to re-design my layers. Linq To Sql - Making a dynamic search for the Application layer without exposing DAL layer as DLL


My project consist of 3 layers: DAL, BL, Application. The Linq2Sql is exsist in the DAL layer and he auto-generate a class to each table in the data base, and a ContextObject to manage the data base. I cant change anything in this classes becouse any change in the DB will couse re-auto-generation of 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

those classes are exposed to the BL layer. The Application layer does not need to be exposed to the LinqClientDBDataContext (ContextObject) so I can't expose the Application layer to any auto-generated code of the Linq2Sql (In this case The Client class). Thats why I made a "Duplicate" class of Client that is generated in the BL layer by the DAL.Client Object :

private BusinessLogic.Client Convert(ClientDataAccessLayer.Client Client)
        {
            return new BusinessLogic.Client(Client.ClientID,..);
        }

The problem comes when I try give the Application layer a IQueryable so the Application layer can dynamicly creat queries and filter the results as he want:

public IQueryable<BusinessLogic.Client> Clients()
        {
            this.MainDB.Clients.Select<ClientDataAccessLayer.Client, BusinessLogic.Client>((ClientDAL1) => Convert(ClientDAL1));
        }
ClientLogic().Clients().Where((ClientBL1)=>ClientBL1.ClientID==4);

Exception: Method 'BusinessLogic.Client Convert(ClientDataAccessLayer.Client)' has no supported translation to SQL.

This code gives this exception and I know why but I cant Find Any better solution for this problem.

Feel free to help me re-design my project so the application can dynamicly query the DB.

Thanks alot, Stav Alfi.

回答1:

You cannot call constructors in your linq-to-sql queries. you'll have to write your converter like this

// NOTE: this is an expression, not a method
private static Expression<Func<ClientDataAccessLayer.Client, BusinessLogic.Client>> Convert =
    x => new BusinessLogic.Client // NOTE: initializer, not a constructor
    {
        Id = x.Id,
        ...
    };

public IQueryable<BusinessLogic.Client> Clients()
{
    this.MainDB.Clients.Select(Convert);
}

Assuming you have no other parts of your query which are calling arbitrary, non-Linq-to-SQL-compatible functions, the error should go away.