I'm defining a variable within an if statement and then trying to use that variable outside the context of that statement. How can I initialize an empty dbSet outside of the if statements so that the viewModel can see/populate it?
This is what I'm trying to accomplish:
if (order.type.ToString() == "Rush")
{
var filteredOrders = db.Orders.Where(a => a.rushID == order.rushID).ToList();
}
else if (order.type.ToString() == "Standard")
{
var filteredOrders = db.Orders.Where(a => a.standardID == order.standardID).ToList();
}
else
{
return HttpNotFound();
}
var viewModel = new OrderDetailsViewModel
{
PastOrders = filteredOrders, // filteredOrders doesn't exist here
Order = order;
};
IEnumerable<Order> filteredOrders; // or IList<Order>, etc., as your prefer
switch (order.type.ToString())
{
case "Rush":
filteredOrders = db.Orders.Where(a => a.rushID == order.rushID).ToList();
case "Standard":
filteredOrders = db.Orders.Where(a => a.standardID == order.standardID).ToList();
default::
return HttpNotFound();
}
var viewModel = new OrderDetailsViewModel
{
PastOrders = filteredOrders,
Order = order;
};
or better:
Func<Order, bool> filter;
switch (order.type.ToString())
{
case "Rush":
filter = a => a.rushID == order.rushID;
case "Standard":
filter = a => a.standardID == order.standardID;
default::
return HttpNotFound();
}
var viewModel = new OrderDetailsViewModel
{
PastOrders = db.Orders.Where(filter).ToList(),
Order = order;
};
Related
I try to compose a dynamic query with NEST (Elastichsearc library for dotnet 5.0) but only the first code work:
Case 1: (Work)
var response1 = await client.SearchAsync<VideoManifestElasticDto>(s =>
s.Query(q => q
.Bool(b => b
.Must(mu => mu
.Wildcard(f => f.Title, '*' + dtoSearch.Title + '*')
))));
var aaa1 = response1.Documents;
Return 4 documents. It's OK
Case 2: (Not Work)
var response2 = await client.SearchAsync<VideoManifestElasticDto>(s =>
s.Query(q => q
.Bool(b => b
.Must(mu => new WildcardQuery() { Field = nameof(VideoManifestElasticDto.Title), CaseInsensitive = true, Value = '*' + dtoSearch.Title + '*' }
))));
var aaa2 = response2.Documents;
Return 0 documents. Why?
Case 3: (Not Work)
Last case, this is my goal i wan't create a dynamic query
var response3 = await client.SearchAsync<VideoManifestElasticDto>(Blah(dtoSearch));
var aaa3 = response3.Documents;
public static SearchDescriptor<VideoManifestElasticDto> Blah(VideoManifestElasticDto videoManifestElasticDto)
{
return new SearchDescriptor<VideoManifestElasticDto>().Query(b => b.Bool( c => c.Must(Orso(videoManifestElasticDto))));
}
public static QueryContainer[] Orso(VideoManifestElasticDto videoManifestElasticDto)
{
List<QueryContainer> queryContainerList = new List<QueryContainer>();
if (videoManifestElasticDto == null)
{
return queryContainerList.ToArray();
}
if (!string.IsNullOrWhiteSpace(videoManifestElasticDto.Title))
{
var orQuery = new WildcardQuery() { Field = nameof(VideoManifestElasticDto.Title), CaseInsensitive = true, Value = '*' + videoManifestElasticDto.Title + '*' };
queryContainerList.Add(orQuery);
}
else if (!string.IsNullOrWhiteSpace(videoManifestElasticDto.Description))
{
var orQuery = new MatchQuery() { Field = "Description", Query = videoManifestElasticDto.Description };
queryContainerList.Add(orQuery);
}
else if (!string.IsNullOrWhiteSpace(videoManifestElasticDto.VideoId))
{
var orQuery = new MatchQuery() { Field = "VideoId", Query = videoManifestElasticDto.VideoId };
queryContainerList.Add(orQuery);
}
return queryContainerList.ToArray();
}
Below is my code
var dbClaimLink = this.Context.Set<ClaimLink>();
var claims = await DbSet
.Include(claim => claim.Parent)
.Include(link => link.ParentLinks)
.ToListAsync();
var newClaimLink = await dbClaimLink.ToListAsync();
var processedClaims = claims.Select(x =>
{
var claimLinks = x.ParentLinks;
if (!claimLinks.Any())
{
return x;
}
var hiddenParents = claimLinks.Select(p => claims.Find(t => t.Id == p.ClaimLinkId));
x.HiddenParents = hiddenParents;
return x;
});
foreach (var objClaim in processedClaims)
{
if (objClaim.Children == null)
objClaim.Children = new List<Claim>();
var lst = newClaimLink.Where(k=> k.ClaimLinkId == objClaim.Id).ToList();
if (lst.Any())
{
foreach (var item in lst)
{
IEnumerable<Claim> newChildren = claims.Where(p => p.Id == item.ClaimId);
objClaim.Children.Concat(newChildren);
}
}
}
it always return old children set without concatenate with new children. I want to those old and new children set concatenate in side of foreach loop
the Concat method returns a new collection with both values and does not alter the original.
Concat will return new object - result of concatination, so you need to save it somewhere: var result = objClaim.Children.Concat(newChildren);
Where is lazy operation, it does not execute in place, only after materialization (ToArray, or foreach call): claims.Where(p => p.Id == item.ClaimId).ToArray()
I am using Entity Framwork with a database-first approach. I want to change the table name or view name dynamically based on conditions.
Here, I am using V_OVT_VLD_340B_DNA_CLD or V_OVT_B_table or V_OVT_c_table to get the records.
Based upon the source, I need to call the different table name and get the records. The whole code snippet is the same, except for the table name.
Please refer below code
private dOVT_OutlierViewEntities db = new dOVT_OutlierViewEntities();
if(source == "a")
{
var result = this.db.V_OVT_VLD_340B_DNA_CLD.Where(x => x.DNA_PGM_PRTN_ID == partitionId && x.CLIENT_ID == clientId).ToList().Select(y => new ValidationModel
{
claim_validation_test_id = new List<byte?> { y.CLAIM_VLD_TEST_ID },
claim_id = y.CLAIM_ID,
Provider_ID = y.Provider_ID,
}).Take(id).ToList();
}
if(source == "b")
{
var result = this.db.v_OVT_B_table.Where(x => x.DNA_PGM_PRTN_ID == partitionId && x.CLIENT_ID == clientId).ToList().Select(y => new ValidationModel
{
claim_validation_test_id = new List<byte?> { y.CLAIM_VLD_TEST_ID },
claim_id = y.CLAIM_ID,
Provider_ID = y.Provider_ID,
}).Take(id).ToList();
}
if(source == "c")
{
var result = this.db.v_OVT_C_table.Where(x => x.DNA_PGM_PRTN_ID == partitionId && x.CLIENT_ID == clientId).ToList().Select(y => new ValidationModel
{
claim_validation_test_id = new List<byte?> { y.CLAIM_VLD_TEST_ID },
claim_id = y.CLAIM_ID,
Provider_ID = y.Provider_ID,
}).Take(id).ToList();
}
I want to modify the above implementation by dynamically attaching the table name to db context based upon condition.
string tableName = string.empty
if(source == "a")
tableName = "aTable";
if(source == "b")
tableName="bTable";
this.db.tableName.where().....
Is that possible?
You can go with a switch condition to set the table type and use that with context
switch (tableName)
{
case "a":
tableType = typeof(V_OVT_VLD_340B_DNA_CLD);
break;
case "b":
tableType = typeof(v_OVT_B_table);
break;
default:
tableType = typeof(v_OVT_C_table);
break;
}
var query = context.Set(tableType);
var result = query.Find(); //filter with this query condition
You can do something like this..
string tableName = string.empty
if(source == "a")
tableName =db.GetTable("aTable");
if(source == "b")
tableName=db.GetTable("bTable");
and then query like..
tableName.where()
I have a issue in EF7/asp.Net Core application. In my context I create a method Save:
public int Save()
{
ChangeTracker.DetectChanges();
var modifiedEntities = ChangeTracker.Entries()
.Where(p => p.State == EntityState.Modified || p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified || p.State == EntityState.Detached).ToList();
var now = DateTime.UtcNow;
foreach (var change in modifiedEntities)
{
var entityName = change.Entity.GetType().Name;
var primaryKeyValue = GetPrimaryKeyValue(change.Entity);
foreach (var prop in change.Entity.GetType().GetTypeInfo().DeclaredProperties)
{
if (!prop.GetGetMethod().IsVirtual)
{
var currentValue = change.Property(prop.Name).CurrentValue;
var originalValue = change.Property(prop.Name).OriginalValue;
if (originalValue.ToString() != currentValue.ToString())
{
var changeLoged = new ChangeLog
{
PropertyName = prop.Name,
EntityName = entityName,
PrimaryKeyValue = primaryKeyValue,
DateChange = now,
OldValue = originalValue.ToString(),
NewValue = currentValue.ToString(),
ChangedBy = "test"
};
ChangeLog.Add(changeLoged);
}
}
}
}
return base.SaveChanges();
}
and method GetPrimaryKeyValue:
protected virtual int GetPrimaryKeyValue<T>(T entity)
{
var test = entity;
var test2 = test.GetType();
var keyName = this.Model.FindEntityType(test2).FindPrimaryKey().Properties
.Select(x => x.Name).Single();
var result = (int)entity.GetType().GetProperty(keyName).GetValue(entity, null);
if (result < 0)
return -1;
return result;
}
Unfortunatlly the change.Property(prop.Name).CurrentValue always equals OriginalValue, so the if
originalValue.ToString() != currentValue.ToString()
always return false.
Replace:
var originalValue = change.Property(prop.Name).OriginalValue;
to:
var originalValue = change.GetDatabaseValues().GetValue<object>(prop.Name);
This will not exactly answer your question since I cannot reproduce this issue but this may help you.
In EF Core, the PropertyEntry class has now an IsModified property which let you know if the value has been modified or not.
You should use it instead:
if (change.Property(prop.Name).IsModified)
{
var changeLoged = new ChangeLog
{
PropertyName = prop.Name,
EntityName = entityName,
PrimaryKeyValue = primaryKeyValue,
DateChange = now,
OldValue = originalValue.ToString(),
NewValue = currentValue.ToString(),
ChangedBy = "test"
};
ChangeLog.Add(changeLoged);
}
Disclaimer: I'm the owner of the project Entity Framework Plus
The Library has an Audit Feature (Supporting EF Core) which you may use or get inspired by to create your auditing (The code is Open Source).
Documentation: EF+ Audit
Based on the answers above I refactored my SetChanges method to this, and its working fine now! (EF 6 and .NET 6)
private void SetChanges()
{
TableName = Entry.Metadata.GetTableName();
var entsInDB = Entry.GetDatabaseValues();
foreach (PropertyEntry property in Entry.Properties)
{
if (property != null)
{
string propertyName = property.Metadata.Name;
if (property.Metadata.IsPrimaryKey())
{
KeyValues[propertyName] = property.CurrentValue ?? "";
continue;
}
switch (Entry.State)
{
case EntityState.Added:
NewValues[propertyName] = property.CurrentValue ?? "";
AuditType = AuditType.Create;
break;
case EntityState.Deleted:
OldValues[propertyName] = property.OriginalValue ?? "";
AuditType = AuditType.Delete;
break;
case EntityState.Modified:
if (property.IsModified)
{
var originalValue = entsInDB?.GetValue<object>(property.Metadata.Name);
if (originalValue?.ToString() != property.CurrentValue?.ToString())
{
ChangedColumns.Add(propertyName);
OldValues[propertyName] = originalValue?.ToString() ?? "";
NewValues[propertyName] = property.CurrentValue ?? "";
AuditType = AuditType.Update;
}
}
break;
}
}
}
}
Logging it to the database audit table:
How can i factorize this code?
my filter returns several type of document. the difficult is that i have some query per type... i would like a generic method to return a correct query
thanks
if(this.comboBoxType.Text.Equals("Vente"))
{
IQueryable<Vente> queryV = ContexteDAO.ContexteDonnees.Vente
.Include("Client")
.Include("Paiement")
.Include("Employe").OrderBy(v => v.venteID);
if (this.tbxNomCli.Text != "")
queryV = queryV.Where(v => v.Client.nom.Contains(this.tbxNomCli.Text));
if (this.comboBoxEtat.Text != "Tous")
queryV = queryV.Where(v => v.etat == this.comboBoxEtat.Text);
if (this.checkBoxDate.Checked)
queryV = queryV.Where(v => v.date.Equals(this.dateTimePicker.Value.Date));
if (this.tbxTva.Text != "")
queryV = queryV.Where(v => v.Client.numEntreprise.Contains(this.tbxTva.Text));
if (this.checkBoxVendeur.Checked)
{
Employe employe = this.comboBoxVendeur.SelectedItem as Employe;
queryV = queryV.Where(v => v.Employe.login.Equals(employe.login));
}
this.documentBindingSource.DataSource = queryV.ToList();
}
if (this.comboBoxType.Text.Equals("Commande"))
{
IQueryable<Commande> queryC = ContexteDAO.ContexteDonnees.Commande
.Include("Client")
.Include("Paiement")
.Include("Employe").OrderBy(c => c.commandeID);
if (this.tbxNomCli.Text != "")
queryC = queryC.Where(v => v.Client.nom.Contains(this.tbxNomCli.Text));
if (this.comboBoxEtat.Text != "Tous")
queryC = queryC.Where(v => v.etat == this.comboBoxEtat.Text);
if (this.checkBoxDate.Checked)
queryC = queryC.Where(v => v.date.Equals(this.dateTimePicker.Value.Date));
if (this.tbxTva.Text != "")
queryC = queryC.Where(v => v.Client.numEntreprise.Contains(this.tbxTva.Text));
if (this.checkBoxVendeur.Checked)
{
Employe employe = this.comboBoxVendeur.SelectedItem as Employe;
queryC = queryC.Where(v => v.Employe.login.Equals(employe.login));
}
this.documentBindingSource.DataSource = queryC.ToList();
}
You could make a generic approach:
public IQueryable<T> GetData<T>( string identifier )
{
switch( identifier )
{
case "Vente":
{
return ContexteDAO.ContexteDonnees.Vente
.Include("Client")
.Include("Paiement")
.Include("Employe")
.OrderBy(v => v.venteID);
// do more stuff
break;
}
// add more cases
default:
{
return null;
}
}
}
the call would look like:
IQueryable<Vente> result = GetData<Vente>( "Vente" );
it would solve your problem but i won't like it, because you need to specify the type AND need an identifier which selection you would like to perform. This could lead to an exception really fast when you have something like GetData<Vente>( "OtherEntity" ).