@@ -73,6 +73,41 @@ module EntityFramework {
7373 /** The class `Microsoft.EntityFrameworkCore.DbSet<>` or `System.Data.Entity.DbSet<>`. */
7474 class DbSet extends EFClass , UnboundGenericClass {
7575 DbSet ( ) { this .getName ( ) = "DbSet<>" }
76+
77+ /** Gets a method that adds or updates entities in a DB set. */
78+ SummarizableMethod getAnAddOrUpdateMethod ( boolean range ) {
79+ exists ( string name | result = this .getAMethod ( name ) |
80+ name in [ "Add" , "AddAsync" , "Attach" , "Update" ] and
81+ range = false
82+ or
83+ name in [ "AddRange" , "AddRangeAsync" , "AttachRange" , "UpdateRange" ] and
84+ range = true
85+ )
86+ }
87+ }
88+
89+ /** A flow summary for EntityFramework. */
90+ abstract class EFSummarizedCallable extends SummarizedCallable { }
91+
92+ private class DbSetAddOrUpdate extends EFSummarizedCallable {
93+ private boolean range ;
94+
95+ DbSetAddOrUpdate ( ) { this = any ( DbSet c ) .getAnAddOrUpdateMethod ( range ) }
96+
97+ override predicate propagatesFlow (
98+ SummaryInput input , ContentList inputContents , SummaryOutput output ,
99+ ContentList outputContents , boolean preservesValue
100+ ) {
101+ input = SummaryInput:: parameter ( 0 ) and
102+ (
103+ if range = true
104+ then inputContents = ContentList:: element ( )
105+ else inputContents = ContentList:: empty ( )
106+ ) and
107+ output = SummaryOutput:: thisParameter ( ) and
108+ outputContents = ContentList:: element ( ) and
109+ preservesValue = true
110+ }
76111 }
77112
78113 /** The class `Microsoft.EntityFrameworkCore.DbQuery<>` or `System.Data.Entity.DbQuery<>`. */
@@ -118,9 +153,6 @@ module EntityFramework {
118153 }
119154 }
120155
121- /** A flow summary for EntityFramework. */
122- abstract class EFSummarizedCallable extends SummarizedCallable { }
123-
124156 /** The struct `Microsoft.EntityFrameworkCore.RawSqlString`. */
125157 private class RawSqlStringStruct extends Struct {
126158 RawSqlStringStruct ( ) { this .getQualifiedName ( ) = "Microsoft.EntityFrameworkCore.RawSqlString" }
@@ -359,7 +391,9 @@ module EntityFramework {
359391 * to a column in the underlying DB.
360392 */
361393 pragma [ noinline]
362- predicate mappedPath ( Property dbSet , PropertyContent head , ContentList tail , Property last ) {
394+ predicate pathFromDbSetToDbProperty (
395+ Property dbSet , PropertyContent head , ContentList tail , Property last
396+ ) {
363397 this .requiresContentList ( head , _, tail , _, last ) and
364398 head .getProperty ( ) = dbSet and
365399 dbSet = this .getADbSetProperty ( _)
@@ -383,12 +417,12 @@ module EntityFramework {
383417 preservesValue = true and
384418 exists ( PropertyContent sourceHead , ContentList sourceTail |
385419 input = SummaryInput:: thisParameter ( ) and
386- c .mappedPath ( _, sourceHead , sourceTail , mapped ) and
420+ c .pathFromDbSetToDbProperty ( _, sourceHead , sourceTail , mapped ) and
387421 inputContents = ContentList:: cons ( sourceHead , sourceTail )
388422 ) and
389423 exists ( Property dbSetProp |
390424 output = SummaryOutput:: jump ( dbSetProp .getGetter ( ) , SummaryOutput:: return ( ) ) and
391- c .mappedPath ( dbSetProp , _, outputContents , mapped )
425+ c .pathFromDbSetToDbProperty ( dbSetProp , _, outputContents , mapped )
392426 )
393427 )
394428 }
0 commit comments