Entity Framework - 2.2
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
The following .NET framework / Libraries are supported by this extension:
Framework / Library name | Version | Supported | Supported Technology | Comments |
---|---|---|---|---|
Entity Framework (EF, EF6) | 3.0 to 6.4.x | ✔️ | C# | |
Entity Framework Core (EF Core) | 1.0.x to 7.0.x | ✔️ | C# | |
Z.EntityFramework.Plus.EF6 | 1.6.4 to 7.21.0 | ✔️ | C# | Entity Framework Plus extends DbContext with must-have features: Include Filter, Auditing, Caching, Query Future, Batch Delete and Batch Update. |
Z.EntityFramework.Plus.EFCore | 2.22.3 to 7.22.4 | ✔️ | C# | Same as above |
EFCore.BulkExtensions | 1.0 to 7.1 | ✔️ | C# | |
LINQ to Entities - method syntax | ✔️ | C# |
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 |
---|---|
✔️ | ✔️ |
Compatibility
CAST Imaging Core release | Supported |
---|---|
8.3.x | ✔️ |
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?
Objects
Icon | Object Type Description | Comment |
---|---|---|
EF Entity | Created when the DbSet Entity is declared in the derived class inheriting from DbContext | |
EF Entity Operation | Used when CRUD operation is performed on Entity | |
EF SQL Query | Used for native queries | |
EF Unknown SQL Query | Used when the query could not be resolved | |
EF Unknown Entity | Created and used when the entity could not be resolved | |
EF Unknown Entity Operation | Used when CRUD operation is performed and Entity could not be resolved |
Links
Link type | Source and destination of link | Methods supported |
---|---|---|
callLink useInsertLink |
callLink between the caller .NET Method object and EF Entity Operation /EF Unknown Entity Operation object useInsertLink between the EF Entity Operation object and Database Table object |
EF Insert Operation APIs
EF Core DbSet & DbContext Insert Operation APIs
Insert Operation supported through ObjectContext APIs
Insert Operation through EFCore.BulkExtensions |
callLink useDeleteLink |
callLink between the caller .NET Method object and EF Entity Operation / EF Unknown Entity Operation object useDeleteLink between the EF Entity Operation object and Database Table object |
EF Delete Operation APIs
EF Core DbSet & DbContext Delete Operation APIs
Delete Operation supported through ObjectContext APIs
Delete Operations supported through EF Plus APIs
Delete Operation through EFCore.BulkExtensions |
callLink useUpdateLink |
callLink between the caller .NET Method object and EF Entity Operation /EF Unknown Entity Operation object useUpdateLink between the EF Entity Operation object and Database Table object |
EF Core DbSet & DbContext Update Operation APIs
Update Operations supported through EF Plus APIs
Update Operation through EFCore.BulkExtensions |
callLink useSelectLink |
callLink between the caller .NET Method object and EF Entity Operation / EF Unknown Entity Operation object useSelecttLink between the EF Entity Operation object and Database Table object |
EF Select Operation APIs
EF Core Select Operation APIs
Microsft.EntityFrameworkCore.EntityFrameworkQueryableExtensions Select Operation APIs
Z.EntityFramework.Plus Select Operation APIs
Select Operations in EF Plus supported through Eval-Expression.Net Library
Select Operation through EFCore.BulkExtensions |
callLink | callLink between the caller .NET Method object and EF SQL Query / EF Unknown SQl Query object |
Execute APIs
Execute APIs supported through ObjectContext APIs |
Code examples
Insert operation
Insert operation
Add
public static void GenerateData()
{
using EntityContext context = new();
context.Customers.Add(new Customer() { Name = "Customer_A", Description = "Description", IsActive = true });
}
Insert Operation through dbcontext.Set<T>
Insert through dbcontext.Set
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
Delete
public override void DeleteEntity(Entities context, object entity)
{
var entityToRemove = (ShelfInspectionCreationPermission)entity;
if (entityToRemove.AdditionApprovalId != null) { context.AdditionApprovals.Remove(entityToRemove.AdditionApproval); }
if (entityToRemove.DeletionApprovalId != null) { context.DeletionApprovals.Remove(entityToRemove.DeletionApproval); }
entityToRemove.User_Depots.ToList().ForEach(ud => ud.ShelfInspectionCreationPermission = null);
context.ShelfInspectionCreationPermissions.Remove(entityToRemove);
}
Delete Operation through ObjectContext
Delete Operation through ObjectContext
public void DeleteACCESS_RIGHT_STATUS(ACCESS_RIGHT_STATUS aCCESS_RIGHT_STATUS)
{
base.DeleteObject(aCCESS_RIGHT_STATUS);
}
Batch Delete Operation through EF Plus
Delete Operation through EF Plus
public override void DeleteEntity(Entities context, object entity)
{
var entityToRemove = (Role_SupplierComplaints_ProcessingStage)entity;
if (entityToRemove.AdditionApprovalId != null) { context.AdditionApprovals.Remove(entityToRemove.AdditionApproval); }
if (entityToRemove.DeletionApprovalId != null) { context.DeletionApprovals.Remove(entityToRemove.DeletionApproval); }
context.Role_SupplierComplaints_ProcessingStage.Remove(entityToRemove);
}
Update Operation
Update operation
Update
public void UpdateContractorAddress()
{
var contractor = dbContext.Contractor.FirstOrDefault();
contractor.Address = ModelFakes.ContractorFake.Generate().Address;
dbContext.Contractor.Update(contractor);
dbContext.SaveChanges();
}
Batch Update Operation through EF Plus
Batch Update Operation through EF Plus
public static void UpdateRows()
{
EntityContext context = new ();
context.Customers.Where(x => x.Name == "Customer_C").Update(x => new Customer {Description = "Updated_C",IsActive = false});
}
Bulk Operations through EFCore.BulkExtensions
Bulk Operations
public static void BulkOperations()
{
List<InvoiceItem> invoiceDetails = new List<InvoiceItem>
{
new InvoiceItem { InvoiceItemId = 1, ProductName ="Apple" },
new InvoiceItem { InvoiceItemId = 2, ProductName = "Orange"},
// Add more invoice details to synchronize
};
var context = new EntityContext();
context.BulkInsertOrUpdateOrDelete(invoiceDetails);
}
Select operation
Select operation
Find
protected void AssignPermissionToUser(User user, int depotId, Entities context)
{
var user_depotEntity = context.User_Depots.Find(user.Id, depotId);
if (user_depotEntity.ShelfInspectionCreationPermission != null)
{
throw new EntityConflictException("Permission already existing or pending.");
}
}
Select operation through Z.EntityFramework.Plus
Select
public static void QueryDeferredTrial()
{
using EntityContext context = new();
//Query Cache
context.Customers.DeferredCount().FromCache();
}
LINQ-To-Entities
LINQ-To-Entities
LINQ-To-Entities
public string[] GetColumnPermissionsOfUser(int id, string tableName)
{
using (var context = new Entities())
{
List<int> userRoles = context.User_Roles
.Where(ur => ur.UserId == id)
.Where(ur => ur.AdditionApproval.ApprovedAt.HasValue)
.Where(ur => ur.Role.AdditionApproval.ApprovedAt.HasValue)
.Select(ur => ur.RoleId)
.ToList();
}
}
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 Asynchronous counterpart results in the similar transaction as above.
Unknown SQL Query
protected void ResetWorkflowProgress(Entities context, DealerComplaint complaint)
{
context.Database.ExecuteSqlCommand(abcd);
complaint.LastDeciderName = null;
complaint.LastDecisionDate = null;
}
Reading of edmx file
edmx file mapping
internal void AddDataChangeApprover(DataChangeApprover dca)
{
_context.DataChangeApprovers.Add(dca);
}
DbContext and DbSet
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; }
}
edmx
<EntitySetMapping Name="DataChangeApprovers">
<EntityTypeMapping TypeName="DispalyConfiguration.DataChangeApprover">
<MappingFragment StoreEntitySet="Approval">
Support for Table Per Hierarchy
Table Per Hierarchy
public class AppDbContext : DbContext
{
public DbSet<CreditCard> CreditCard { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BillingDetail>().ToTable("BankingBillingDetails");
}
}
public abstract class BillingDetail
{
[Required]
public int BillingDetailId { get; set; }
public string Owner { get; set; }
public string Number { get; set; }
}
public class CreditCard : BillingDetail
{
public int CardType { get; set; }
public string ExpiryMonth { get; set; }
public string ExpiryYear { get; set; }
}
Unknown Entity
Unknown Entity
public class BaseRepository<TEntity> : IRepository<TEntity>
where TEntity : class
{
private WP2AlertsContext alertsContext;
public BaseRepository(WP2AlertsContext wP2Context)
{
alertsContext = wP2Context;
}
public virtual async Task<TEntity> AddAsync(TEntity entity)
{
await alertsContext.AddAsync(entity);
alertsContext.Entry(entity).State = EntityState.Added;
await alertsContext.SaveChangesAsync();
return entity;
}
}
Assumptions
- SaveChanges() method of DbContext class commits the operation in the database table. Hence no useLink is created between caller method and table.
Limitations
-
Analyzing the participating database tables is mandatory for the extension to produce appropriate useLinks
-
LINQ-Entity Query syntax is not supported
-
Unknown Entity object gets created in case the entity in the CRUD transaction does not get resolved. In such a case, the caller method will get connected to the Unknown Entity Operation object of the Unknown Entity.
-
Unknown SQL Query object gets created if the query used in the execution does not get resolved.