Extension ID
com.castsoftware.entity
What's new?
See Entity Framework 2.2 - Release Notes for more information.
Description
This extension provides support for Entity Framework. The calculation of Automated Function Points for your .NET analyses will be supplemented through the links between objects produced by the base .NET Analyzer and database tables, using Entity Framework CRUD operations.
In what situation should you install this extension?
If your .NET application contains Entity Framework source code and you want to view these object types and their links, then you should install this extension. More specifically the extension will identify:
- "call" links from C# methods using Entity Framework operations to Entity framework operation objects
- "use" links from Entity framework operation objects to participating Database tables
Technology support
Entity Framework
Entity Framework is delivered with the .NET Framework. Therefore the following .NET frameworks are supported by this extension:
Version | Supported | Supported Technology |
---|
3.0 and above |  | C# |
Entity Framework Core
Entity Framework Core is supported when using AIP Core 8.3.x and above as Entity Framework Core is delivered with .NET Core.
Function Point, Quality and Sizing support
This extension provides the following support:
- Function Points (transactions): a green tick indicates that OMG Function Point counting and Transaction Risk Index are supported
- Quality and Sizing: a green tick indicates that CAST can measure size and that a minimum set of Quality Rules exist
Function Points (transactions) |  |
---|
Quality and Sizing |  |
---|
AIP Core compatibility
This extension is compatible with:
| |
---|
8.3.x |  |
Supported DBMS servers
This extension is compatible with the following DBMS servers:
DBMS | Supported |
---|
CSS/PostgreSQL |  |
Prerequisites
 | An installation of any compatible release of AIP Core (see table above) |
Download and installation instructions
The extension will be automatically downloaded and installed in CAST Console. You can manage the extension using the Application - Extensions interface:

What results can you expect?
Once the analysis/snapshot generation has completed, you can view the results in the normal manner. The following links will be displayed in CAST Enlighten:
Objects
Icon | Description |
---|
| Entity |
| Entity Operation |
| Entity SQL Query |
Links
Link type | Source and destination of link | Methods supported |
---|
callLink useInsertLink | callLink between the caller .NET Class / Method object and Entity Operation useInsertLink between the Entity Operation object and Database Table object | EF Insert Operation APIs - System.Data.Entity.DbSet.Add
- System.Data.Entity.DbSet.AddRange
EF Core DbSet & DbContext Insert Operation APIs - Microsoft.EntityFrameworkCore.DbSet.Add
- Microsoft.EntityFrameworkCore.DbSet.AddRange
- Microsoft.EntityFrameworkCore.DbSet.AddAysnc
- Microsoft.EntityFrameworkCore.DbSet.AddRangeAsync
- Microsoft.EntityFrameworkCore.DbContext.AddRange
- Microsoft.EntityFrameworkCore.DbContext.AddRangeAsync
- Microsoft.EntityFrameworkCore.DbContext.Add
- Microsoft.EntityFrameworkCore.DbContext.AddAsync
Insert Operation supported through ObjectContext APIs - System.Data.Objects.ObjectContext.AddObject
- System.Data.Objects.ObjectSet.AddObject
- System.Data.Entity.Core.Objects.ObjectContext.AddObject
|
callLink useDeleteLink | callLink between the caller .NET Class / Method object and Entity Operation useDeleteLink between the Entity Operation object and Database Table object | EF Delete Operation APIs - System.Data.Entity.DbSet.Remove
- System.Data.Entity.DbSet.RemoveRange
EF Core DbSet & DbContext Delete Operation APIs - Microsoft.EntityFrameworkCore.DbSet.Remove
- Microsoft.EntityFrameworkCore.DbSet.RemoveRange
- Microsoft.EntityFrameworkCore.DbContext.Remove
Delete Operation supported through ObjectContext APIs - System.Data.Objects.ObjectContext.DeleteObject
- System.Data.Objects.ObjectSet.DeleteObject
- System.Data.Entity.Core.Objects.ObjectContext.DeleteObject
|
callLink useUpdateLink | callLink between the caller .NET Class / Method object and Entity Operation useUpdateLink between the Entity Operation object and Database Table object | EF Core DbSet & DbContext Update Operation APIs - Microsoft.EntityFrameworkCore.DbSet.Update
- Microsoft.EntityFrameworkCore.DbSet.UpdateRange
- Microsoft.EntityFrameworkCore.DbContext.Update
|
callLink useSelectLink | callLink between the caller .NET Class / Method object and Entity Operation useSelecttLink between the Entity Operation object and Database Table object | EF Select Operation APIs - System.Data.Entity.DbSet.Attach
- System.Data.Entity.DbSet.Create
- System.Data.Entity.DbSet.Equals
- System.Data.Entity.DbSet.Find
- System.Data.Entity.DbSet.FindAsync
- System.Data.Entity.DbSet.GetHashCode
- System.Data.Entity.DbSet.GetType
- System.Data.Entity.DbSet.Include
- System.Data.Entity.DbSet.SqlQuery
- System.Data.Entity.DbSet.ToString
- System.Data.Entity.QueryableExtensions.FirstOrDefaultAsync
- System.Data.Entity.QueryableExtensions.FirstAsync
- System.Data.Entity.QueryableExtensions.AllAsync
- System.Data.Entity.QueryableExtensions.AnyAsync
- System.Data.Entity.QueryableExtensions.ForEachAsync
- Many select operations belonging to System.Linq.Enumerable and System.Linq.Queryable
EF Core Select Operation APIs - Microsoft.EntityFrameworkCore.DbSet.Find
- Microsoft.EntityFrameworkCore.DbSet.FindAsync
- Microsoft.EntityFrameworkCore.DbSet.GetAsyncEnumerator
- Microsoft.EntityFrameworkCore.DbSet.GetHashCode
- Microsoft.EntityFrameworkCore.DbSet.ToString
- Microsoft.EntityFrameworkCore.DbSet.Equals
- Microsoft.EntityFrameworkCore.DbSet.Attach
- Microsoft.EntityFrameworkCore.DbSet.AttachRange
- Microsoft.EntityFrameworkCore.DbSet.AsQueryable
- Microsoft.EntityFrameworkCore.DbSet.AsAsyncEnumerable
|
callLink | callLink between the caller .NET Class / Method object and Entity SQL Query | Execute APIs - System.Data.Entity.Database.ExecuteSqlCommand
- System.Data.Entity.Database.ExecuteSqlCommandAsync
- Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlCommand
- Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlCommandAsync
- Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRaw
- Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRawAsync
- Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSql
- Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSqlRaw
- Microsoft.EntityFrameworkCore.RelationalQueryableExtensions.FromSqlInterpolated
Execute APIs supported through ObjectContext APIs - System.Data.Objects.ObjectContext.ExecuteFunction
- System.Data.Objects.ObjectContext.ExecuteStoreCommand
- System.Data.Objects.ObjectContext.ExecuteStoreQuery
- System.Data.Entity.Core.Objects.ObjectContext.ExecuteFunction
- System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreCommand
- System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQuery
- System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreCommandAsync
- System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryAsync
|
Code examples
Insert operation
Insert operation
public void AddNewContractor()
{
var contractor = ModelFakes.ContractorFake.Generate();
var vendor = dbContext.Vendor.FirstOrDefault();
contractor.VendorId = vendor.Id;
dbContext.Contractor.Add(contractor);
dbContext.SaveChanges();
Assert.AreNotEqual(0, contractor.Id);
}

Insert Operation through dbcontext.Set<T>
Insert through dbcontext.Set<T>
public void SaveCalculatedCycles(string discriminator, IEnumerable<AuditCycle> calculatedCycles)
{
foreach (AuditCycle cycle in calculatedCycles)
{
MissionAuditCycle saveableCycle = new MissionAuditCycle
{
DateOfEarliestAuditPerformed = cycle.DateOfEarliestAuditPerformed,
StartDate = cycle.StartDate,
EndDate = cycle.EndDate,
MissionDiscriminatorWithoutIndex = discriminator,
ShiftId = cycle.ShiftId
};
_dbContext.Set<MissionAuditCycle>().Add(saveableCycle);
}
}

Insert Operation through ObjectContext
Insert Operation through ObjectContext
public void AddToACCESS_RIGHT_STATUS(ACCESS_RIGHT_STATUS aCCESS_RIGHT_STATUS)
{
base.AddObject("ACCESS_RIGHT_STATUS", aCCESS_RIGHT_STATUS);
}

Delete operation
Delete operation
public void RemoveEntry()
{
var rec = dbContext.Contractor.FirstOrDefault();
dbContext.Contractor.Remove(rec);
dbContext.SaveChanges();
}

Delete Operation through ObjectContext
Delete Operation through ObjectContext
public void DeleteACCESS_RIGHT_STATUS(ACCESS_RIGHT_STATUS aCCESS_RIGHT_STATUS)
{
base.DeleteObject(aCCESS_RIGHT_STATUS);
}

Update Operation
Update operation
public void UpdateContractorAddress()
{
var contractor = dbContext.Contractor.FirstOrDefault();
contractor.Address = ModelFakes.ContractorFake.Generate().Address;
dbContext.Contractor.Update(contractor);
dbContext.SaveChanges();
}

Select operation
Select operation
public void FindEntry(int id)
{
var rec = dbContext.Vendor.Find(id);
dbContext.SaveChanges();
}

LINQ-To-Entities
LINQ-To-Entities
public static void LinqToEntitiesQueries()
{
using (var context = new SchoolDBEntities())
{
//Log DB commands to console
context.Database.Log = Console.WriteLine;
//Retrieve students with the same name - Linq-to-Entities Method Syntax
var studentsWithSameName = context.Students
.GroupBy(s => s.StudentName)
.Where(g => g.Count() > 1)
.Select(g => g.Key);
}
}

Support for EntityModelConfiguration
EntityModelConfiguration allows configuration to be performed for any entity type in a model. Support has be been provided to create callLink between method and entity operation object and appropriate crud link between entity operation object and table, when table name is overridden through EntityModelConfiguration.
EntityModelConfiguration
public DomainModel.Portaalstatus OpslaanLogin(Account account)
{
using (new LoggingMonitoredScope(LogConstants.Diagnostics))
{
ValidationHelper.Validate(account);
if (ClaimHelper.IsMeekijker())
return new DomainModel.Portaalstatus();
var cacheKey = CacheSettingsHelper.CreateCacheKey(account);
_cacheHelper.Remove(cacheKey, CacheGroups.CacheGroupPortaalStatussen);
DomainModel.Portaalstatus cacheItem;
using (var dbContext = new ApfPortalenDbContext())
{
var portaalstatus =
dbContext.Portaalstatussen.FirstOrDefault(
p => p.AdministratieId.Equals(account.AdministratieIdentificatie) &&
p.RelatienummerDeelnemerMaia.Equals(account.RelatienummerDeelnemerMAIA));
if (portaalstatus == null)
{
portaalstatus = dbContext.Portaalstatussen.Add(new Portaalstatus());
}
};
}


Support for CRUD operations using dbContext
CRUD using dbcontext
public async Task<IActionResult> Create(Distribution distribution)
{
if (ModelState.IsValid)
{
context.Add(distribution);
await context.SaveChangesAsync();
return RedirectToAction("Index");
}
else
return View();
}

Support for ExecuteSqlQuery
ExecuteSqlCommand
protected void InsertInfo(List<DispatcherInfo> entities)
{
int chunkSize = 1000;
var pendingBar = new PendingBar(Logger);
pendingBar.Start();
Entities context = new Entities();
try
{
entities.GroupBy(e => e.DepotId).ToList().ForEach(g =>
{
context.Database.ExecuteSqlCommand("DELETE FROM DispatcherInfoes WHERE DepotId = {0}", g.Key);
context.BulkInsert(g.ToList(), chunkSize);
context.SaveChanges();
});
}
catch (Exception)
{
throw;
}
finally
{
pendingBar.Stop();
if (context != null)
context.Dispose();
}
}
}

Use of FromSql, FromSqlRaw, FromSqlInterpoated, ExecuteFunction, ExecuteStoreCommand, ExecuteStoryQuery, ExecuteStoreCommand, ExecuteSqlCommand and their Asynchrnous counterpart results in the similar transaction as above.
Reading of edmx file
edmx file mapping
internal void AddDataChangeApprover(DataChangeApprover dca)
{
_context.DataChangeApprovers.Add(dca);
}
public partial class DisplayConfigEntities : DbContext
{
public DisplayConfigEntities()
: base("name=DisplayConfigEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<DataChangeApprover> DataChangeApprovers { get; set; }
}
<EntitySetMapping Name="DataChangeApprovers">
<EntityTypeMapping TypeName="DispalyConfiguration.DataChangeApprover">
<MappingFragment StoreEntitySet="Approval">

Functionality
Along with the better positioning of the bookmarks, the following features are supported in this version
- Both Entity Framework 6 and EntityFramework Core
- CRUD operation executed using APIs of DbSet class
- CRUD operations performed through dbcontext
- CRUD operations executed using APIs belonging to ObjectContext class
- Asynchronous API and batch operations
- Insert, Delete operations performed through dbcontext.Set<T>
- Mapping between entity and table provided through edmx file
- Creation of entities through edmx file only when ObjectContext is used
- LINQ-to-Entities for Method Syntax only
Assumptions
- SaveChanges() method of DbContext class commits the operation in the database table. Hence no useLink is created between caller method and table.
- When the class is referenced in other code as a property, parent and child relation is created. Any CRUD operation performed on parent class is also reflected in the child class. e.g. In the below case, data is inserted in Contractor, but useInsertLink is created for both Contractor and Vendor tables, as Vendor is referenced in Contractor (foreign key):

Limitations
- Analyzing the participating database tables is mandatory for the extension to produce appropriate useLinks
- Select operations performed through dbcontext.Set<T> are not supported
- LINQ-Entity Query syntax is not supported