linq query for update more than one record - visual-studio-2010

I have a table named industries. In this my fields are
workfor_id,
workfor_usr_id,
workfor_industry_id.
With the same values of workfor_id, I have different workfor_industry_id's.
foreach (var k in us){
var ind = dbContext.industries.Where(i => i.workfor_id ==
k.id).Select(i => i).FirstOrDefault();
string ind2 = k.industry;
var industryParts = ind2.Split(',');
var o = (industryParts.Length);
for (c = 0; c < o; c++){
ind.workfor_id = Convert.ToInt16(k.id);
ind.workfor_industry_id = Convert.ToInt16(k.industryid); }
}
To update workfor_industry_id field I have implemented inner loop inside the foreach loop to get the values of workfor_industry_id's.here same record is over loading with different workfor_industry_id's.
can you tell me how to implement this.

UPDATED
This update adds a little more error checking and assumes that -1 is never a valid value for industry_id
short GetShort(string value) {
short returnValue;
value = (value ?? string.Empty).Replace("\"",null);
return short.TryParse(value, out returnValue) ? returnValue : (short)-1;
}
foreach (var k in us){
var id=Convert.ToInt16(k.id);
var toRemove=from i in dbContext.industries
where i.workfor_id == k.id
select i;
var toAdd = from x in (k.industry ?? string.Empty).Split(',')
select new Industry {
workfor_id=id,
workfor_industry_id=GetShort(x)
};
dbContext.industries.DeleteAllOnSubmit(toRemove);
dbContext.industries.InsertAllOnSubmit(toAdd.Where(x=>x.workfor_industry_id != -1));
}
dbContext.SubmitChanges();

Related

Dynamics crm + plugin logic to update zero values

I need to perform the sum of each field across multiple records of the same entity and update the values on the same entity. Along with this I also need to store its formula.
AttributeList = { "price ", "quantity", "contact.revenue", "opportunity.sales"}
Below is the logic
foreach (var attribute in attributeList)
{
Decimal fieldSum = 0;
string computedNote = string.Empty;
foreach (var entity in mainEntityList)
{
if (entity.Contains(attribute))
{
if (entity.Attributes[attribute] != null)
{
string type = entity.Attributes[attribute].GetType().Name;
Decimal attrValue = 0;
if (type == "AliasedValue")
{
AliasedValue aliasedFieldValue = (entity.GetAttributeValue<AliasedValue>(attribute));
attrValue = aliasedFieldValue.Value.GetType().Name == "Decimal" ? (Decimal)aliasedFieldValue.Value : (Int32)aliasedFieldValue.Value;
}
else
{
attrValue = entity.Attributes[attribute].GetType().Name == "Decimal" ? entity.GetAttributeValue<Decimal>(attribute) : entity.GetAttributeValue<Int32>(attribute);
}
fieldSum += attrValue;
computedNote += $"+{Convert.ToInt32(attrValue).ToString()}";
}
}
else
{
computedNote += $"+0";
}
}
Entity formula = new Entity("formula");
if (fieldSum != 0)
{
if (attribute.Contains("opportunity"))
{
opportunity[attributeName] = fieldSum;
entityName = Opportunity.EntityLogicalName;
attributeName = attribute;
recordId = Id;
}
else if (attribute.Contains("contact"))
{
contact[attributeName] = fieldSum;
entityName = Contact.EntityLogicalName;
attributeName = attribute;
recordId = Id;
}
else
{
mainentity[attribute] = fieldSum;
entityName = mainEntity.EntityLogicalName;
attributeName = attribute;
recordId = Id;
}
formula.Attributes["ice_entity"] = entityName;
formula.Attributes["ice_attribute"] = attributeName;
formula.Attributes[entityName + "id"] = new EntityReference(entityName, recordId);
formula.Attributes["ice_computednote"] = computedNote.Remove(0, 1);
requestsCollection.Entities.Add(formula);
}
}
requestsCollection.Entities.Add(opportunity);
requestsCollection.Entities.Add(contact);
requestsCollection.Entities.Add(mainentity);
Values in both records could be as follows
Record 1
Price = 500
Quantity = 25
Revenue = 100
Sales = 10000
Volume = 0
Record 2
Price = 200
Quantity = 10
Revenue = 100
Sales = -10000
Volume = 0
Record 3 (Values after calculation that are to be updated in the third entity and Formula to be stored mentioned in brackets)
Price = 700 Formula = (500+200)
Quantity = 35 Formula = (25+10)
Revenue = 200 Formula =(100+100)
Sales = 0 Formula =(10000 + (-10000))
Volume = 0 No Formula to be created
I am checking if the fieldsum is not equal to zero (to update both positive and negative values) and then updating the values in the respective entity. However for values that became zero after the calculation. I also need to update them and create formula for the same. Avoiding the values that were zero by default.
As shown in above example, I want to update sales field value and create formula record for the same as '10000+-10000' but do not want volume field value to be updated or the formula to be created for it. How can i embed this logic in my code?
Add a flag (updateFormula) to indicate whether checksum and formula required to update in related entities. Then, instead of checking fieldSum != 0, check updateFormula is true to update the related records.
attributeList = { "price", "quantity", "contact.revenue", "opportunity.sales"}
foreach (var attribute in attributeList)
{
Decimal fieldSum = 0;
string computedNote = string.Empty;
bool updateFormula = false;
foreach (var entity in mainEntityList)
{
if (entity.Contains(attribute))
{
if (entity.Attributes[attribute] != null)
{
string type = entity.Attributes[attribute].GetType().Name;
Decimal attrValue = 0;
if (type == "AliasedValue")
{
AliasedValue aliasedFieldValue = (entity.GetAttributeValue<AliasedValue>(attribute));
attrValue = aliasedFieldValue.Value.GetType().Name == "Decimal" ? (Decimal)aliasedFieldValue.Value : (Int32)aliasedFieldValue.Value;
}
else
{
attrValue = entity.Attributes[attribute].GetType().Name == "Decimal" ? entity.GetAttributeValue<Decimal>(attribute) : entity.GetAttributeValue<Int32>(attribute);
}
fieldSum += attrValue;
computedNote += Convert.ToInt32(attrValue).ToString();
updateFormula = true;
}
}
else
{
computedNote += 0;
}
}
Entity formula = new Entity("formula");
if (updateFormula)
{
// Logic to update formula and checksum
}
}

Code Rewite for tuple and if else statements by using LINQ

In my C# application i am using linq. I need a help what is the syntax for if-elseif- using linq in single line. Data, RangeDate are the inputs. Here is the code:
var Date1 = RangeData.ToList();
int record =0;
foreach (var tr in Date1)
{
int id =0;
if (tr.Item1 != null && tr.Item1.port != null)
{
id = tr.Item1.port.id;
}
else if (tr.Item2 != null && tr.Item2.port != null)
{
id = tr.Item2.port.id;
}
if (id >0)
{
if(Data.Trygetvalue(id, out cdat)
{
// Do some operation. (var cdata = SumData(id, tr.item2.port.Date)
record ++;
}
}
}
I think your code example is false, your record variable is initialized to 0 on each loop so increment it is useless .
I suppose that you want to count records in your list which have an id, you can achieve this with one single Count() :
var record = Date1.Count(o => (o.Item1?.port?.id ?? o.Item2?.port?.id) > 0);
You can use following code:
var count = RangeData.Select(x => new { Id = x.Item1?.port?.id ?? x.Item2?.port?.id ?? 0, Item = x })
.Count(x =>
{
int? cdate = null; // change int to your desired type over here
if (x.Id > 0 && Data.Trygetvalue(x.Id, out cdat))
{
// Do some operation. (var cdata = SumData(x.Id, x.Item.Item2.port.Date)
return true;
}
return false;
});
Edit:
#D Stanley is completely right, LINQ is wrong tool over here. You can refactor few bits of your code though:
var Date1 = RangeData.ToList();
int record =0;
foreach (var tr in Date1)
{
int? cdat = null; // change int to your desired type over here
int id = tr.Item1?.port?.id ?? tr.Item2?.port?.id ?? 0;
if (id >0 && Data.Trygetvalue(id, out cdat))
{
// Do some operation. (var cdata = SumData(id, tr.Item2.port.Date)
record ++;
}
}
Linq is not the right tool here. Linq is for converting or querying a collection. You are looping over a collection and "doing some operation". Depending on what that operation is, trying to shoehorn it into a Linq statement will be harder to understand to an outside reader, difficult to debug, and hard to maintain.
There is absolutely nothing wrong with the loop that you have. As you can tell from the other answers, it's difficult to wedge all of the information you have into a "single-line" statement just to use Linq.

how to use variable value in LINQ to entity

Here is my code
if (Count < LeaveTypeCount)
{
for (int i = 0; i < LeaveTypeCount; i++)
{
var LeaveId = from l in CompObj.LeaveTypes
select l.LeaveID;
var leaveIdArray = LeaveId.ToArray ();
var LeaveDefault = (from c in CompObj.LeaveTypes
where (c.LeaveID ==leaveIdArray[i])
select new { c.DefaultLeave }).FirstOrDefault();
Int32 DefaultCount = Convert.ToInt32(LeaveDefault.DefaultLeave);
AssignedLeave AddObj = new AssignedLeave();
AddObj.EmpID = EmpID;
AddObj.AssignedYear = LeaveYear;
AddObj.LeaveID =leaveIdArray[i];
AddObj.TotalLeave = DefaultCount;
CompObj.AssignedLeaves.AddObject(AddObj);
CompObj.SaveChanges();
}
}
but its showing error The LINQ expression node type 'ArrayIndex' is not supported in LINQ to Entities.
How can i resolve this issue or what is the another way to do this task
Thanks
You just need to copy the value to a local variable:
var leaveIdValue = leaveIdArray[i];
var LeaveDefault = (from c in CompObj.LeaveTypes
where (c.LeaveID ==leaveIdValue)
select new { c.DefaultLeave }).FirstOrDefault();
BTW, you should probably move leaveIdArray out of the loop, since it doesn't depend on the value of i.

how to improve the performance of function which takes almost 1 second in loading time (asp.net mvc 3)

I did a profile tracing to check what functions are taking long times , One of the method takes near 1 second and is called 10+ times and i guess it should be a candidate for review. I have included the method, Can anyone tell me how can it possible be improved.
[NonAction]
private ProductModel.ProductMiscModel PrepareProductMiscModel(Product product)
{
if (product == null)
throw new ArgumentNullException("product");
var model = new ProductModel.ProductMiscModel();
var productVariants = _productService.GetProductVariantsByProductId(product.Id);
var getManufactureImage = _manufacturerService.GetProductManufacturersByProductId(product.Id)
.Select(x =>
{
var m = x.Manufacturer.ToModel();
m.PictureModel.ImageUrl = _pictureService.GetPictureUrl(x.Manufacturer.PictureId, _mediaSetting.ManufacturerThumbPictureSize, true);
m.PictureModel.Title = string.Format(_localizationService.GetResource("Media.Manufacturer.ImageLinkTitleFormat"), m.Name);
m.PictureModel.AlternateText = string.Format(_localizationService.GetResource("Media.Manufacturer.ImageAlternateTextFormat"), m.Name);
return m;
})
.ToList();
model.manufactureName = getManufactureImage;
switch (productVariants.Count)
{
case 0:
{
//var productVariant = productVariants[0];
model.Sku = null;
model.ShowSku = false;
// model.attributeName = 0;
} break;
case 1:
//only one variant
{ var productVariant = productVariants[0];
model.Sku = productVariant.Sku; //null;
model.ShowSku = true;
// model.attributeName = _productAttributeService.GetProductVariantAttributesByProductVariantId(productVariant.Id);
model.productSpecification = _specificationAttributeService.GetProductSpecificationAttributesByProductId(productVariant.Product.Id);
}
break;
}
return model;
}
_manufactureService.GetProductManufactureByProductId
public virtual IList<ProductManufacturer> GetProductManufacturersByProductId(int productId, bool showHidden = false)
{
if (productId == 0)
return new List<ProductManufacturer>();
string key = string.Format(PRODUCTMANUFACTURERS_ALLBYPRODUCTID_KEY, showHidden, productId);
return _cacheManager.Get(key, () =>
{
var query = from pm in _productManufacturerRepository.Table
join m in _manufacturerRepository.Table on
pm.ManufacturerId equals m.Id
where pm.ProductId == productId &&
!m.Deleted &&
(showHidden || m.Published)
orderby pm.DisplayOrder
select pm;
var productManufacturers = query.ToList();
return productManufacturers;
});
}
Use StopWatch in the method to determine which part it is that takes long time.
you might want to include the picture url in the original list instead of traversing each item and call _pictureService.GetPictureUrl.

Entity Framework ObjectContext.SaveChanges fails on unique key column update

Consider very simple database table:
CREATE TABLE UkTest(
id int NOT NULL,
uk int NOT NULL
)
Primary Key on id
Unique Key on uk
Then add 2 rows:
INSERT INTO UkTest (id,uk) VALUES(1,1);
INSERT INTO UkTest (id,uk) VALUES(2,2);
Then do 2 tests.
OK:
var db = new Database1Entities();
var element1 = db.UkTest.FirstOrDefault(e => e.id == 1);
var element2 = db.UkTest.FirstOrDefault(e => e.id == 2);
element1.uk = 0;
element2.uk = 1; // overrides previous element1.uk value
var count = db.SaveChanges();
Fails (before test revert uk values to 1 and 2!):
var db = new Database1Entities();
var element1 = db.UkTest.FirstOrDefault(e => e.id == 1);
var element2 = db.UkTest.FirstOrDefault(e => e.id == 2);
element2.uk = 0;
element1.uk = 2; // overrides previous element2.uk value
var count = db.SaveChanges();
// Cannot insert duplicate key row in object 'dbo.UkTest' with unique index 'UK_UkTest'
See that ObjectContext.SaveChanges() checks rows in the order of primary index.
Is there any way to force own order?
Unless you call SaveChanges() twice, no, there is no way to control the order of SQL statements Entity Framework will send to the database. You could wrap the multiple SaveChanges() calls into an outer transaction to ensure still a transactional behaviour for the whole operation:
using (var scope = new TransactionScope())
{
using (var db = new Database1Entities())
{
var element1 = db.UkTest.FirstOrDefault(e => e.id == 1);
var element2 = db.UkTest.FirstOrDefault(e => e.id == 2);
element2.uk = 0;
db.SaveChanges();
element1.uk = 2;
db.SaveChanges();
}
scope.Complete();
}
Thanks to Slauma. I've found the solution. The key is to keep elements in several ObjectContext instances.
public class SavingElementsWithTransactionInOwnOrder
{
public void SaveElements ()
{
var db = new Database1Entities();
var element1 = db.UkTest.FirstOrDefault(e => e.id == 1);
element1.db = db;
db = new Database1Entities();
var element2 = db.UkTest.FirstOrDefault(e => e.id == 2);
element2.db = db;
element2.uk = 0;
element1.uk = 2;
var scope = new TransactionScope();
try{
element2.db.SaveChanges();
element1.db.SaveChanges();
scope.Complete();
}
finally{
scope.Dispose();
}
}
}
public partial class UkTest
{
public Database1Entities db { get; set; }
}

Resources