Store Monolog in database - database

I have been creating an application with Symfony 4.2, I want to save all logs in database, I'm using MonologBundle.
Monolog.yml
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine", "!console"]
I want to store data in database like this
How Can I do this with Symfony.

You can achieve that by creating a custom monolog channel (e.g. doctrine_channel) and handler (e.g. doctrine) to go with it. Update the example below as per your needs.
Monolog configuration
monolog:
channels: [doctrine_channel]
handlers:
main:
...
channels: [... !doctrine_channel]
console:
...
channels: [... !doctrine_channel]
doctrine:
type: service
channels: [doctrine_channel]
id: app.logger.doctrine_handler
Service configuration
services:
app.logger.doctrine_handler:
class: App\Logger\DoctrineHandler
arguments:
- "#doctrine.orm.entity_manager"
DoctrineHandler
namespace App\Logger;
use App\Entity\Log;
use Doctrine\ORM\EntityManagerInterface;
use Monolog\Handler\AbstractProcessingHandler;
class DoctrineHandler extends AbstractProcessingHandler
{
private $initialized;
private $entityManager;
private $channel = 'doctrine_channel';
public function __construct(EntityManagerInterface $entityManager)
{
parent::__construct();
$this->entityManager = $entityManager;
}
protected function write(array $record)
{
if (!$this->initialized) {
$this->initialize();
}
if ($this->channel != $record['channel']) {
return;
}
$log = new Log();
$log->setMessage($record['message']);
$log->setLevel($record['level_name']);
$this->entityManager->persist($log);
$this->entityManager->flush();
}
private function initialize()
{
$this->initialized = true;
}
}
Result
mysql> SELECT * FROM log;
+----+----------+-----------+---------------------+
| id | message | level | created_at |
+----+----------+-----------+---------------------+
| 1 | Welcome! | INFO | 2019-02-07 19:00:00 |
| 2 | Go back! | WARNING | 2019-02-07 19:00:05 |
| 3 | Help! | EMERGENCY | 2019-02-07 19:00:10 |
+----+----------+-----------+---------------------+
3 rows in set (0.00 sec)
Then inject #monolog.logger.doctrine_channel (type hinted LoggerInterface) to your service or wherever you want to log something. This should work! Now, it is up to you to refactor/enhance as you wish.

Related

Assigning values to arrays with dynamic keys in nested objects in javascript

I have problems understanding and creating dynamic keys of an object and assigning values to nested objects.
desired output:
{
SULS: {
"Main Site": ["Home Page", "Login Page", "Register Page"],
"Judge Site": ["Login Page", "Submittion Page"],
"Digital Site": ["Login Page"],
},
Lamba: {
CoreA: ["A23", "A24", "A25"],
CoreB: ["B24"],
},
Indice: {
Session: ["Default Storage", "Default Security"]
},
}
here is the input:
system([
"SULS | Main Site | Home Page",
"SULS | Main Site | Login Page",
"SULS | Main Site | Register Page",
"SULS | Judge Site | Login Page",
"SULS | Judge Site | Submittion Page",
"Lambda | CoreA | A23",
"SULS | Digital Site | Login Page",
"Lambda | CoreB | B24",
"Lambda | CoreA | A24",
"Lambda | CoreA | A25",
"Lambda | CoreC | C4",
"Indice | Session | Default Storage",
"Indice | Session | Default Security",
]);
This is what i have been trying and keep getting errors while constructing the nested object:
function system(components) {
let obj = components.reduce((mainObj, input) => {
let [systemName, component, subComponent] = input.split(" | ");
return {
...mainObj,
[systemName]: {
...(mainObj[systemName] || {}),
[component]: [...(mainObj[systemName][component] || []), subComponent],
},
};
}, {});
console.log(obj);
}
I have been stucked for a few days and appreciate if anyone can help
Your code has the correct logic. There is just an error on this line:
[component]: [...(mainObj[systemName][component] || []), subComponent],
...when mainObj[systemName] is still undefined.
This is easily solved with optional chainging:
[component]: [...(mainObj[systemName]?.[component] || []), subComponent],

404 not found for laravel api Url's

I have api call from react to laravel as backend
const response=await fetch("http://localhost:8000/api/getcandidates/");
but I got response as Kanban.jsx:65
GET http://localhost:8000/api/getcandidates/ 404 (Not Found)
and here is my api.php
Route::get('/getcandidates',[EmployeeController::class,'index']);
Route::get('/getcandidates_schedule',[EmployeeController::class,'scheduleresponse']);
Route::get('/getcandidates_rejection',[EmployeeController::class,'rejectionreponse']);
Route::get('/getcandidates_waiting',[EmployeeController::class,'waitingresponse']);
Route::post('/add_employee_first',[EmployeeController::class,'store']);
Route::post('/updatecolumn',[EmployeeController::class,'updatecolumn']);
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
output of php artisan route:list:
Domain | Method | URI | Name | Action | Middleware |
+--------+----------+----------+------+---------+------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/user | | Closure | api |
| | | | | | auth:api |
+--------+----------+----------+------+---------+------------
Please help me .

Why my laravel passport stopped working when migrated to vagrant from build-in server?

So I had to implement facebook login, which requires https connection, before I was using php artisan serve, but it only allows http, now I decided to migrate whole project to vagrant. Everything works fine but passport.
I checked and found that theese two lines are causing internal error 500
auth()->attempt($loginData, true);
auth()->user()->createToken('authToken')->accessToken;
when removed, I get no error. My whole login function look like this:
public function login(Request $request)
{
$loginData = $request->validate([
'name' => 'required',
'password' => 'required'
]);
$a = auth()->attempt($loginData, true);
if(!$a) {
return response(['message'=>'Invalid credentials', 'auth' => false]);
}
$accessToken = auth()->user()->createToken('authToken')->accessToken;
return response(['user' => auth()->user(), 'access_token' => $accessToken, 'auth' => true, "attempt" => $a, "auth()" => auth()]);
}
In addition, I've created users via tinker, tokens and users were stored.
here is my db data
mysql> select * from users;
+----+-------+--------------------------------------------------------------+----------------+---------------------+---------------------+
| id | name | password | remember_token | created_at | updated_at |
+----+-------+--------------------------------------------------------------+----------------+---------------------+---------------------+
| 1 | admin | $2y$10$V8fM6Vvc7xOJxN/LPyImUeQNzG9/k3tSsaF8qf1NsxrzK9B3VPmsa | NULL | 2019-08-26 15:22:02 | 2019-08-26 15:22:02 |
| 2 | demis | $2y$10$oRvcL0ZC2NQuGXE446GhfO1KBcAw3h8d/TGQmODL/AFHnat1I.Yvq | NULL | 2019-08-26 15:45:27 | 2019-08-26 15:45:27 |
+----+-------+--------------------------------------------------------------+----------------+---------------------+---------------------+
2 rows in set (0.00 sec)
mysql> select * from oauth_access_tokens;
+----------------------------------------------------------------------------------+---------+-----------+-----------+--------+---------+---------------------+---------------------+---------------------+
| id | user_id | client_id | name | scopes | revoked | created_at | updated_at | expires_at |
+----------------------------------------------------------------------------------+---------+-----------+-----------+--------+---------+---------------------+---------------------+---------------------+
| 2e82923d6fdc1cc98580b683952b7b96d555e67d6b7e06b8080f8a55227b6c1d7a755fc21b570941 | NULL | 1 | authToken | [] | 0 | 2019-08-26 15:21:52 | 2019-08-26 15:21:52 | 2020-08-26 15:21:52 |
| 610f8fd1f2212ab257810de88605bff4e419f26477bcf63f8dfe20018d9bcf74797bb9c817d6450a | NULL | 1 | authToken | [] | 0 | 2019-08-26 15:45:19 | 2019-08-26 15:45:19 | 2020-08-26 15:45:19 |
+----------------------------------------------------------------------------------+---------+-----------+-----------+--------+---------+---------------------+---------------------+---------------------+
What's wrong, Why I can't login, maybe there's something wrong with configuration?
Run php artisan passport:install on the new server.

Randomising eventId of Post body with random ${orgId} but getting error as The input was not valid

I am trying to generate a random eventid with orgId but getting this below error ,this error clearly states that input data to the event in invalid,when i change the evnet id to 1 ,code works fine ,only when i try to randomise it ,i am getting the below error message
14:59:36.475 [WARN ] i.g.h.a.ResponseProcessor - Request 'CreateEventRound-GameKeeper' failed: status.find.in(200,201), but actually found 400
Session(Game Keeper Post Orgs ,1,Map(access_token -> eyJhbGciOiJSUzI1NiIsImtpZCI6IjM0NmM4YTY1NTBlZGI5MDRjM2IyNWI3ODlmOTllNjU3ODA4MGJiOTUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJpa3J3dWdoMzg3MWdodzhyZ243cTgzZ2giLCJleHAiOjE1NTU0NTI4NjgsImlhdCI6MTU1NTQ1MTk2OCwiaXNzIjoiNzZIRktZNzVHUkEyTFBHQ1pETVZYUTY2SEEiLCJzdWIiOiJZTUdDWFA2SVVCSE9QRkdLNDVYUUdON1RWNCIsIndvdGMtbmFtZSI6IktvemlsZWtzVHJhbnNsYXRvckRldiM1MjIxMyIsIndvdGMtZG9tbiI6InRhYmxldG9wIiwid290Yy1nYW1lIjoiZXZlbnRyZXBvcnRlcmRldiIsIndvdGMtZmxncyI6MCwid290Yy1yb2xzIjpbXSwid290Yy1wcm1zIjpbXSwid290Yy1zY3BzIjpbImZpcnN0LXBhcnR5Il19.SqMnINmD7q2FC1Zyf34xbaWOP3LhRtdbL44ZkY3vDKa2-E2yEv4fX1-f8dJTWzOVDNOJYLkHZCrKu8YkVqvO1u9RP5d-Kyfpm1GMVqV9duFPKOuRkgg6p8xxDy3jg0o-ItMZa3fYNNe-3GQ2BdGmxPv7fnoov-OSIY6F7XQAEdnGUc5uMxID_4BrKYZmpBDuzi3LPPaUJeHGdh_nOJvhq-sIUHFmIpp3e70VE9xLvjQ8uS8vJI1fGCq7tDvpXtFFtCPTQ05LLD_SIvt2uPULn80SHA8aH37cI0Zpu4eeDyy0sBjRSPXSK8vKEwhUDsbt_u02s-8O9BPeCJ4RLu8EfQ, gatling.http.cache.dns -> io.gatling.http.resolver.ShuffleJdkNameResolver#319ab5e5, gatling.http.cache.contentCache -> io.gatling.core.util.cache.Cache#619cf254, token_type -> Bearer, orgId -> 29, eventId -> ["The input was not valid.","The input was not valid."], 721cad9b-2343-46f4-8f2f-766319bc197b -> 8, e803e068-608b-4826-a7ab-7f7eff07fadb -> 0),1555451967893,23,KO,List(ExitOnCompleteLoopBlock(721cad9b-2343-46f4-8f2f-766319bc197b), ExitOnCompleteLoopBlock(e803e068-608b-4826-a7ab-7f7eff07fadb)),io.gatling.core.protocol.ProtocolComponentsRegistry$$Lambda$412/1842952737#70e2ec5d)
14:59:37.484 [WARN ] i.g.h.a.ResponseProcessor - Request 'CreateEventRound-GameKeeper' failed: status.find.in(200,201), but actually found 400
Session(Game Keeper Post Orgs ,1,Map(access_token -> eyJhbGciOiJSUzI1NiIsImtpZCI6IjM0NmM4YTY1NTBlZGI5MDRjM2IyNWI3ODlmOTllNjU3ODA4MGJiOTUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJpa3J3dWdoMzg3MWdodzhyZ243cTgzZ2giLCJleHAiOjE1NTU0NTI4NjgsImlhdCI6MTU1NTQ1MTk2OCwiaXNzIjoiNzZIRktZNzVHUkEyTFBHQ1pETVZYUTY2SEEiLCJzdWIiOiJZTUdDWFA2SVVCSE9QRkdLNDVYUUdON1RWNCIsIndvdGMtbmFtZSI6IktvemlsZWtzVHJhbnNsYXRvckRldiM1MjIxMyIsIndvdGMtZG9tbiI6InRhYmxldG9wIiwid290Yy1nYW1lIjoiZXZlbnRyZXBvcnRlcmRldiIsIndvdGMtZmxncyI6MCwid290Yy1yb2xzIjpbXSwid290Yy1wcm1zIjpbXSwid290Yy1zY3BzIjpbImZpcnN0LXBhcnR5Il19.SqMnINmD7q2FC1Zyf34xbaWOP3LhRtdbL44ZkY3vDKa2-E2yEv4fX1-f8dJTWzOVDNOJYLkHZCrKu8YkVqvO1u9RP5d-Kyfpm1GMVqV9duFPKOuRkgg6p8xxDy3jg0o-ItMZa3fYNNe-3GQ2BdGmxPv7fnoov-OSIY6F7XQAEdnGUc5uMxID_4BrKYZmpBDuzi3LPPaUJeHGdh_nOJvhq-sIUHFmIpp3e70VE9xLvjQ8uS8vJI1fGCq7tDvpXtFFtCPTQ05LLD_SIvt2uPULn80SHA8aH37cI0Zpu4eeDyy0sBjRSPXSK8vKEwhUDsbt_u02s-8O9BPeCJ4RLu8EfQ, gatling.http.cache.dns -> io.gatling.http.resolver.ShuffleJdkNameResolver#319ab5e5, gatling.http.cache.contentCache -> io.gatling.core.util.cache.Cache#619cf254, token_type -> Bearer, orgId -> 30, eventId -> ["The input was not valid.","The input was not valid."], 721cad9b-2343-46f4-8f2f-766319bc197b -> 9, e803e068-608b-4826-a7ab-7f7eff07fadb -> 0),1555451967893,17,KO,List(ExitOnCompleteLoopBlock(721cad9b-2343-46f4-8f2f-766319bc197b), ExitOnCompleteLoopBlock(e803e068-608b-4826-a7ab-7f7eff07fadb)),io.gatling.core.protocol.ProtocolComponentsRegistry$$Lambda$412/1842952737#70e2ec5d)
================================================================================
2019-04-16 14:59:37 16s elapsed
---- Requests ------------------------------------------------------------------
> Global (OK=3 KO=10 )
> Event-Reservations-Web-Image-Login (OK=1 KO=0 )
> Http Header Token Authentication Url (OK=1 KO=0 )
> Token Generation Url For Post (OK=1 KO=0 )
> CreateEventRound-GameKeeper (OK=0 KO=10 )
---- Errors --------------------------------------------------------------------
> status.find.in(200,201), but actually found 400 10 (100.0%)
Here is the code
val usersDataSource =jsonFile("C:/Gatling2/gatling3james/src/gatling/resources/dat
a/input-gamekeeper.json").circular
val nameDataSource
=jsonFile("C:/Gatling2/gatling3james/src/gatling/resources/data
/input-gamekeeper-StringBody.json").random
var idNumbers=(21 to 33).iterator
def getNextOrgId()=
{
if(!idNumbers.hasNext)
idNumbers=(21 to 33).iterator
Map("orgId"->idNumbers.next())
}
val customFeeder=Iterator.continually(getNextOrgId())
def createEventRound()={
repeat(990000000){
exec(flushHttpCache)
feed(customFeeder)
.exec(http("CreateEventRound-GameKeeper")
//exec(http("CreateEventRound-GameKeeper")
.post("https://api.tabletop-stage.tiamat-origin.cloud/dev/gamekeeper/Round")
.headers(headers_10)
.body(StringBody(session =>
"""
|{
| "eventId": ${orgId},
| "roundStart": "2019-04-16T18:22:50.388Z",
| "roundEnd": "2019-04-16T18:22:50.388Z",
| "currentTime": "2019-04-16T18:22:50.388Z",
| "roundNumber": 1,
| "matches": [
| {
| "matchId": 0,
| "isBye": true,
| "tableNumber": "string",
| "teams": [
| {
| "teamId": 0,
| "teamName": "string",
| "players": [
| {
| "personaId": "string",
| "displayName": "string"
| }
| ]
| }
| ]
| }
| ]
|}
""".stripMargin)).asJSON
.check(status.in(200,201))//checkforaspecificstatus
.check(jsonPath(path="$.roundNumber").is("1"))
.check(jsonPath(path="$.eventId").saveAs(key="eventId")))
//
.check(jsonPath(path="$.displayName").
saveAs(key="displayName")))//checkforaspecificstatus
.exec{session=>println(session);session}
//parameterfortheorgIdgoeshere
.pause(1)
}
}
// add a scenario
val scenario2 = scenario("Game Keeper Post Orgs ")
.exec(http("Event-Reservations-Web-Image-Login")
.get("https://api.origin.cloud/dev/event-reservations-
web/img/loading.dfbfd678.svg")
.headers(headers_1)
.resources(http("Http Header Token Authentication Url")
.options(uri03 + "/auth/oauth/token")
.headers(headers_7),
http("Token Generation Url For Post")
.post(uri03 + "/auth/oauth/token")
.headers(headers_8)
.formParam("grant_type", "password")
.formParam("username", "zyz#wss.com")
.formParam("password", "fJC2RuVdvmHB")
.basicAuth("ikrwugh3871ghw8rgn7q83gh","NbnEEqmDLSfno315o87ghFGYr3jybtzbi76sr")
.check(jsonPath("$.access_token").exists.saveAs("access_token"))
.check(jsonPath("$.token_type").exists.saveAs("token_type"))
))
.forever() { // add in the forever() method - users now loop forever
exec(createEventRound())
}
// setup the load profile
// example command line: ./gradlew gatlingRun-
simulations.RuntimeParameters -DUSERS=10 -DRAMP_DURATION=5 -DDURATION=30
setUp(
scenario2.inject(
nothingFor(5 seconds),
rampUsers(userCount) over ( rampDuration ))
.protocols(httpConf))
.maxDuration(testDuration)
}
Please note if i simply remove the ${orgId} with 1,code works fine,but only i see error when i use ${orgId},kindly suggest where am i going wrong?
I suspect your issue is in your use of
.body(StringBody(session =>
in "createEventRound" which results in the string literal "${orgId}" being submitted
in your example, you're not looking to do any manual manipulation of session values, you just want to retrieve the value of ${orgId}. You could do this by just providing an Expression string to the StringBody.
So...
.body(StringBody( """
|{
| "eventId": ${orgId},
...
}""".stripMargin)).asJSON

DB Intercept causing SQL Nested too deeply

I'm using a DB intercept in entity framework 6 (code first model) in order to implement a soft delete function, however intermittently I'm getting a exception thrown from SQL Server stating "Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries."
This is an example of the sql being generated, as you can see the SQL generated is pretty outrageous:
https://gist.github.com/junderhill/87caceac728809a8ca837b9d8b5189f3
The code for my EF Intercept is as follows:
public class SoftDeleteInterceptor : IDbCommandTreeInterceptor
{
public const string IsDeletedColumnName = "IsDeleted";
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext.OriginalResult.DataSpace != DataSpace.SSpace)
{
return;
}
var queryCommand = interceptionContext.Result as DbQueryCommandTree;
if (queryCommand != null)
{
interceptionContext.Result = HandleQueryCommand(queryCommand);
}
}
private static DbCommandTree HandleQueryCommand(DbQueryCommandTree queryCommand)
{
var newQuery = queryCommand.Query.Accept(new SoftDeleteQueryVisitor());
return new DbQueryCommandTree(
queryCommand.MetadataWorkspace,
queryCommand.DataSpace,
newQuery);
}
public class SoftDeleteQueryVisitor : DefaultExpressionVisitor
{
public override DbExpression Visit(DbScanExpression expression)
{
var table = (EntityType)expression.Target.ElementType;
if (table.Properties.All(p => p.Name != IsDeletedColumnName))
{
return base.Visit(expression);
}
var binding = expression.Bind();
return binding.Filter(
binding.VariableType
.Variable(binding.VariableName)
.Property(IsDeletedColumnName)
.NotEqual(DbExpression.FromBoolean(true)));
}
}
Update:
This did work correctly. However, something was causing significant slow-downs on our servers over time. Every time we would reset the IIS app pool, it would be fast, but it appears EF is somehow caching or leaking memory and slowing it down. We pulled the interceptors out temporarily.
We hit this issue at work, and after a serious amount of time, here's a solution (has yet to be extensively tested; I'll update this with any updates if needed):
To start at the root, in SoftDeleteQueryVisitor, if you need to add the filter, you return return binding.Filter(...), which modifies the query. This in turn triggers TreeCreated. This walks the tree, finds the DbScanExpression again, and re-adds the filter. The obvious solution is to not add the filter if it already has it, then.
Looking at the structure of the tree, we find that the filter is a parent node of the scan:
+ queryCommand {DbQueryCommandTree
|_Parameters
| |_p__linq__0 : Edm.Guid
|_Query : Collection{Record['IDGUID'=Edm.Guid, 'Name'=Edm.String, 'FooField'=Edm.String, 'BarField'=Edm.Boolean, 'Group'=Edm.String, 'IsDeleted'=Edm.Boolean]}
|_Project
|_Input : 'Limit1'
| |_Limit
| |_Filter
| | |_Input : 'Extent1'
| | | |_Filter
| | | |_Input : 'Var_8'
| | | | |_Scan : CodeFirstDatabase.LeaderboardSuite
| | | |_Predicate
| | | |_
| | | |_Var(Var_8).IsDeleted
| | | |_<>
| | | |_True
| | |_Predicate
| | |_
| | |_Var(Extent1).IDGUID
| | |_=
| | |_#p__linq__0
| |_2
|_Projection
|_NewInstance : Record['IDGUID'=Edm.Guid, 'Name'=Edm.String, 'FooField'=Edm.String, 'BarField'=Edm.Boolean, 'Group'=Edm.String, 'IsDeleted'=Edm.Boolean]
|_Column : 'IDGUID'
| |_Var(Limit1).IDGUID
|_Column : 'Name'
| |_Var(Limit1).Name
|_Column : 'FooField'
| |_Var(Limit1).FooField
|_Column : 'BarField'
| |_Var(Limit1).BarField
|_Column : 'Group'
| |_Var(Limit1).Group
|_Column : 'IsDeleted'
|_Var(Limit1).IsDeleted} System.Data.Entity.Core.Common.CommandTrees.DbQueryCommandTree
However, once we realize we own both the visitor and the visitor's lifetime, we realize we can store state:
var newQuery = queryCommand.Query.Accept(new SoftDeleteQueryVisitor());
We also know that the Filter node will be hit before the Scan node because it is a parent of the Scan node. At this point, we have to consider two possibilities: There is no where clause on the query, and there is a where clause on the query.
At this point, I just walked the tree, determined if the query predicate used the IsDeleted field in an Equals or NotEquals clause, and didn't add the node there if so. I didn't bother checking the Or or Xor clauses because these are incredibly unlikely cases. They are easy to add, though, if you find you need them.
public class SoftDeleteQueryVisitor : DefaultExpressionVisitor
{
private readonly List<DbScanExpression> _scanExpressions = new List<DbScanExpression>();
public override DbExpression Visit(DbScanExpression expression)
{
var table = (EntityType)expression.Target.ElementType;
if (table.Properties.All(p => p.Name != InterceptorConstants.IsDeletedColumnName))
{
return base.Visit(expression);
}
if (_scanExpressions.Contains(expression))
{
return base.Visit(expression);
}
var binding = expression.Bind();
return binding.Filter(
binding.VariableType
.Variable(binding.VariableName)
.Property(InterceptorConstants.IsDeletedColumnName)
.NotEqual(DbExpression.FromBoolean(true)));
}
private bool HasField(DbScanExpression expression)
{
var table = (EntityType)expression.Target.ElementType;
return table.Properties.Any(p => p.Name == InterceptorConstants.IsDeletedColumnName);
}
private bool HasExpression(DbExpression predicate)
{
if (predicate is DbAndExpression andExpression)
{
return HasExpression(andExpression.Left) || HasExpression(andExpression.Right);
}
if (predicate is DbComparisonExpression comparisonExpression &&
(comparisonExpression.ExpressionKind == DbExpressionKind.NotEquals ||
comparisonExpression.ExpressionKind == DbExpressionKind.Equals))
{
if (comparisonExpression.Right is DbPropertyExpression rightPropertyExpression &&
rightPropertyExpression.Property.Name == InterceptorConstants.IsDeletedColumnName ||
comparisonExpression.Left is DbPropertyExpression leftPropertyExpression &&
leftPropertyExpression.Property.Name == InterceptorConstants.IsDeletedColumnName)
{
return true;
}
}
return false;
}
public override DbExpression Visit(DbFilterExpression expression)
{
if (expression.Input.Expression is DbScanExpression scanExpression)
{
if (HasField(scanExpression))
{
if (HasExpression(expression.Predicate))
{
_scanExpressions.Add(scanExpression);
}
}
}
return base.Visit(expression);
}
}

Resources