Cannot update lead record in CRM? - c#

My code does not seem to be updating the Lead entity. I have created a new Lead(); as you can see in the code and there is no update when I save the record. Is there something I am doing wrong? This way of updating is just as sufficient as updating by doing crmContext.UpdateObject(oLead); crmContext.SaveChanges();. Can someone please help me with why this is not updating the lead? There is a similar question that just refers to the basic plugin but instead of create I am updating.
private List<Product> GetSectionAProducts()
{
List<Product> products = new List<Product>();
var QEproduct = new QueryExpression("product");
// Add all columns to QEproduct.ColumnSet
QEproduct.ColumnSet.AllColumns = true;
// Define filter QEproduct.Criteria
QEproduct.Criteria.AddCondition("productnumber", ConditionOperator.BeginsWith, "MGIP");
var QEproduct_Criteria_0 = new FilterExpression();
QEproduct.Criteria.AddFilter(QEproduct_Criteria_0);
// Define filter QEproduct_Criteria_0
QEproduct_Criteria_0.AddCondition("capg_billingtimeframe", ConditionOperator.Equal, (int)capg_billingcycletype.Monthly);
QEproduct_Criteria_0.AddCondition("capg_mincriteria", ConditionOperator.NotNull);
QEproduct_Criteria_0.AddCondition("capg_maxcriteria", ConditionOperator.NotNull);
QEproduct_Criteria_0.AddCondition("price", ConditionOperator.NotNull);
EntityCollection results = this.OrganizationService.RetrieveMultiple(QEproduct);
if (results.Entities != null)
{
// Retrieve all records from the result set.
foreach (Entity product in results.Entities)
{
products.Add(new Product { Id = product.Id, capg_MinCriteria = (int?)product.Attributes["capg_mincriteria"], capg_MaxCriteria = (int?)product.Attributes["capg_maxcriteria"], Price = (Money)product.Attributes["price"] });
}
}
return products;
}
var duesproduct = sectionA.Where(o => o.capg_MinCriteria.Value <= dues).ToList().OrderByDescending(o => o.capg_MaxCriteria).FirstOrDefault();
if (duesproduct != null)
{
Xrm.Lead oLead = new Lead();
oLead.Id = this.InputTargetEntity.Id;
oLead.capg_CalculatedDuesBilling = new Money(duesproduct.Price == null ? 0 : duesproduct.Price.Value);
if (duesproduct.capg_MaxCriteria <= 100000)
{
oLead.capg_CalculatedDuesBilling = new Money(Math.Round((duesproduct.Price == null ? 0 : duesproduct.Price.Value) * new decimal(0.0290), 2));
}
if (duesproduct.capg_MaxCriteria <= 235000)
{
oLead.capg_CalculatedDuesBilling = new Money(Math.Round((duesproduct.Price == null ? 0 : duesproduct.Price.Value) * new decimal(0.0262), 2));
}
this.OrganizationService.Update(oLead);
}

I highly recommend you updating records with the IOrganizationService.Update directly, not the context. Context is handy for queries, because you can use LINQ, but when you update entities via the context those might be sent to CRM as an update with all the entity attributes you selected, and that could cause weird behaviors because might trigger unexpected workflows. It also fills the Audit History really quickly.
It is much better to create a new instance of a lead, and populate it with the attributes and Id you want to update, only, and call service.Update.

Related

Entity is incorrectly detaching from tracking EF Core

I am trying to query objects from a database, loop through them and check if a column has a value and, if it does not, create a value and assign it to that column and save it to the database. The problem I'm having is that the entity is detaching after the query so I cannot save the changes. Below is the code I am using to query and update the entity.
DateTime runTime = passedDateTime ?? DateTime.Now;
await using DiscordDatabaseContext database = new();
DateTime startOfWeek = exactlyOneWeek ? runTime.OneWeekAgo() : runTime.StartOfWeek(StartOfWeek);
//Add if not in a Weekly Playlist already and if the video was submitted after the start of the week
List<PlaylistData> pld = await database.PlaylistsAdded.Select(playlist => new PlaylistData
{
PlaylistId = playlist.PlaylistId,
WeeklyPlaylistID = playlist.WeeklyPlaylistID,
Videos = playlist.Videos.Where(
video => (video.WeeklyPlaylistItemId == null ||
video.WeeklyPlaylistItemId.Length == 0) &&
startOfWeek <= video.TimeSubmitted)
.Select(video => new VideoData
{
WeeklyPlaylistItemId = video.WeeklyPlaylistItemId,
VideoId = video.VideoId
}).ToList()
}).ToListAsync().ConfigureAwait(false);
int count = 0;
int nRows = 0;
foreach (PlaylistData playlistData in pld)
{
if (string.IsNullOrEmpty(playlistData.WeeklyPlaylistID))
{
playlistData.WeeklyPlaylistID = await YoutubeAPIs.Instance.MakeWeeklyPlaylist().ConfigureAwait(false);
}
foreach (VideoData videoData in playlistData.Videos)
{
PlaylistItem playlistItem = await YoutubeAPIs.Instance.AddToPlaylist(videoData.VideoId, playlistId: playlistData.WeeklyPlaylistID, makeNewPlaylistOnError: false).ConfigureAwait(false);
videoData.WeeklyPlaylistItemId = playlistItem.Id;
++count;
}
}
nRows += await database.SaveChangesAsync().ConfigureAwait(false);
The query works correctly, I get all relevant Playlist and Video Rows to work with, they have the right data in only the specified columns, and the query that is logged looks good, but saves do not work and calling database.Entry() on any of the Playlists or Video objects show that they are all detached. What am I doing wrong? Are collections saved a different way? Should my query be changed? Is there a setting on initialization that should be changed? (The only setting I have set on init that I feel like may affect this is .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery) but the query logged isn't even split as far as I can see)
You work with projected objects
PlaylistData
VideoData
Projected objects does not tracked by EF core as far as I know. So the solution is to select DbSet's entity objects (mean types that specified in database.PlaylistsAdded and playlist.Videos properties) or select those objects before update and then update them.
UPDATE:
Example code for second option:
foreach (PlaylistData playlistData in pld)
{
var playlist = database.PlaylistsAdded
.Include(x=> x.Videos)
.First(x => x.PlaylistId == playlistData.playlistData);
if (string.IsNullOrEmpty(playlistData.WeeklyPlaylistID))
{
playlist.WeeklyPlaylistID = await YoutubeAPIs.Instance.MakeWeeklyPlaylist().ConfigureAwait(false);
}
foreach (VideoData videoData in playlistData.Videos)
{
var video = playlist.Videos.First(x=> x.VideoId == videoData.VideoId);
PlaylistItem playlistItem = await YoutubeAPIs.Instance.AddToPlaylist(videoData.VideoId, playlistId: playlistData.WeeklyPlaylistID, makeNewPlaylistOnError: false).ConfigureAwait(false);
video.WeeklyPlaylistItemId = playlistItem.Id;
++count;
}
}
NOTICE: this would produce double select's so first option is more preferred

C# MongoDB Update / Upsert List<Object> to Collection

I was searching for a way to Update / Upsert in MongoDB a List of items to a MongoDB collection.
Is there any way to do it or I have to use a loop to update the items one by one?
P.S: The problem is not making a method that would do the Job (one by one) but I want to avoid too much iterations with the MongoDB database.
Here's the method that I'm currently using:
public static void UpdateAll()
{
var client = new MongoClient("mongodb://server_ip:27017");
var db = client.GetDatabase("M_PROJECT");
var collection = db.GetCollection<Product>("products");
//Config.Products is a List<Product> that was previously retrieved from the same collection in MongoDB
foreach(Product product in Config.Products)
{
var filter = Builders<Product>.Filter.Eq(p => p.ID, product.ID);
var update = Builders<Product>.Update.Set("Name", product.Name).Set("Price", 20);
collection.UpdateOne(filter, update, new UpdateOptions() { IsUpsert = true });
}
}
And maybe without specifying every Field/Property that I want to update, but just applying the class instance.
try a bulk replace like so:
var models = new List<WriteModel<Product>>();
foreach (var product in Config.Products)
{
if (product.ID == null) product.ID = ObjectId.GenerateNewId();
var upsert = new ReplaceOneModel<Product>(
filter: Builders<Product>.Filter.Eq(p => p.ID, product.ID),
replacement: product)
{ IsUpsert = true };
models.Add(upsert);
}
collection.BulkWrite(models);
the thing to note here is that it will completely overwrite the data stored in the db with the data from your product class instances. but i think you'd be okay cause you said the products are retrieved from the same collection.
this is what my library MongoDB.Entities does internally to achieve products.Save()
Yes, you can use UpdateMany() instead of UpdateOne(). See https://www.mongodb.com/blog/post/quick-start-csharp-and-mongodb--update-operation and https://mongodb.github.io/mongo-csharp-driver/2.9/apidocs/html/M_MongoDB_Driver_IMongoCollectionExtensions_UpdateMany__1.htm for more details.

Adding new row to DBContext in Entity Framework is overriding last entry

Problem:
Every time I add a new record, it overwrites the last record, thus after looping through, always leaves the table with 1 record.
List<Accounting_InvoiceCheck> liIC = new List<Accounting_InvoiceCheck>();
foreach (Accounting_Invoice invoice in liInvoices.OrderBy(x => x.EntityID).ThenBy(x => x.VendorID))
{
Accounting_InvoiceCheck ic = new Accounting_InvoiceCheck();
ic = invoiceMaster.Check;
ctxAcct.Accounting_InvoiceCheck.add(ic);
//ctxAcct.Entry(ic).State = EntityState.Added
}
ctxAcct.SaveChanges()
The Above code only takes the last record, so the count is always 1 no matter what. Very frustrating when I see everybody else's code online doing just that.
Synopsis
I am using Entity Framework 6 in an MVC5 application. So I have 2 tables that are being updated when I call a method. The table names are Invoices and InvoiceChecks. The relation is, Invoices is the main table, and when you pay an invoice, you create a record in InvoiceChecks.
Below the code is trying to add it in 2 ways (both are there for your purpose to see). One is to create a list of InvoiceChecks, then call ctx.AddRange(liIC) which leaves the table with only the last item in liIC. Another way I've tried is looping through and calling ctx.entry(ic).state = EntityState.Added which is overriding the last row every time it is called.
Any ideas as to why, no matter how I add, the last row is always overwritten?
List<Accounting_InvoiceCheck> liIC = new List<Accounting_InvoiceCheck>();
foreach (Accounting_Invoice invoice in liInvoices.OrderBy(x => x.EntityID).ThenBy(x => x.VendorID))
{
Accounting_InvoiceCheck ic = new Accounting_InvoiceCheck();
ic = invoiceMaster.Check;
ic.InvoiceID = invoice.ID;
var sumAmt = ctx.Accounting_InvoiceChecks.Where(x => x.InvoiceID == invoice.ID).GroupBy(x => x.InvoiceID).Select(x => new { TransAmt = x.Sum(s => s.CKAmt) });
decimal amt = 0;
if (sumAmt.ToList().Count > 0)
{
amt = sumAmt.FirstOrDefault().TransAmt;
}
amt += invoice.AmtPaying;
ctx.Entry(invoice).Entity.AmtPaying = ic.TransAmt - amt;
ctx.Entry(invoice).State = EntityState.Modified;
ctx.Entry(ic).State = EntityState.Added;
//ctx.Accounting_InvoiceChecks.Add(ic);
//liIC.Add(ic);
}
ctx.Accounting_InvoiceChecks.AddRange(liIC);
ctx.SaveChanges();
Updated:
So I discovered that the below code adds it correctly. However, my question is why does the below code work and ic = new Accounting_InvoiceCheck() at the beginning of the foreach loop not work?
ctxAcct.Accounting_InvoiceChecks.Add(new Accounting_InvoiceCheck()
{
InvoiceID = ic.InvoiceID,
AcctPeriod = ic.AcctPeriod,
BankID = ic.BankID,
CheckDate = ic.CheckDate,
CheckNo = ic.CheckNo,
CKAmt = ic.CKAmt,
Description = ic.Description,
TransAmt = ic.TransAmt,
VendorID = ic.VendorID
});

How can I edit or add to a particular field without pull the all object

How I can do just this ( a.myFavorits.Add()) without pulling the all object to var a , because a has a lot of data, and I don't want to pull all a object, but I can't find a way do do it.
I want to do the lambada and the linq without return something but linq is always return something
public static void addFavorits(long f,long idUser)
{
using (var db = dataBase())
{
// here i pull object user from users table
var a = db.users.Where(c => c.id == idUser).SingleOrDefault();
// here i adding to the object field myFavorits new value
//myFavorits is also a table of entitys that connected to user object
a.myFavorits.Add(new BE.FavoritsUsersLong { myLong = f });
db.SaveChanges();
}
}
I thought to do something like this but i dont know how to set the field users_TableId that is the key that connect the 2 tables
public static void addFavorits(long favoritId,long idUser)
{
using (var db = dataBase())
{
db.favoritsUsersLong.Add(new BE.FavoritsUsersLong {myLong = favoritId}
/*,users_TableId =idUser*/);
db.SaveChanges();
}
}
Here's a concrete example that does what you want. In this example, only the Name of a Company is modified and saved. Or an item is added to one of its collections.
var cmp = new Company{ CmpId = 1, Name = "Cmp1" }; // CmpId is the primary key
db.Companies.Attach(cmp);
db.Entry(cmp).Property(c => c.Name).IsModified = true;
// Or add an entity to a collection:
cmp.Users = new[] {new User { Name = "a1", PassWord = "a1" } };
try
{
db.Configuration.ValidateOnSaveEnabled = false;
db.SaveChanges();
}
finally
{
db.Configuration.ValidateOnSaveEnabled = true;
}
Result in SQL:
DECLARE #0 VarChar(30) = 'Cmp1'
DECLARE #1 Int = 1
UPDATE [dbo].[Company]
SET [Name] = #0
WHERE ([CmpId] = #1)
There are a few things to note here:
Obviously you need to know the Id of the entity you want to modify.
The object you create is called a stub entity, which is an incomplete entity. When you try to save such an entity, EF is very likely to complain about null values in required properties. That's why almost certain you'd have to disable validation (temporarily, or, better, dispose the context immediately).
If you want to add an item to a collection, you should leave validation enabled, because you'd want to know for sure that the new entity is valid. So you shouldn't mix these two ways to use a stub entity.
If you often need roughly the same small part of your entity you may consider table splitting.
I'm guessing this is what you want? I don't see you 'editting' I only see you adding.
using (var db = dataBase())
{
var a = new user();
....
//set properties etc..
...
a.myFavorits.Add(new BE.FavoritsUsersLong { myLong = f });
db.users.Add(a);
db.SaveChanges();
}

LINQ to Entities Foreign key associations

I am new to asp.net, C# and sql and could use some guidance.. I am using the :below: db with the linq-to-entities framework. I need to associate a particular 'Ride' with a particular 'Vehicle' but am unsure exactly how to proceed. I have set a navigation property between the two objects but now need to let the vehicle hold a reference to a list of the rides it takes. Do I need a separate column in vehicle to hold this list of rides? Could someone please show me the syntax to accomplish this?
Here is the code I currently have, with comments at the two spots I need help:
private void setNewRide(Ride newRide, int carNum)
{
using (myEntities = new RamRideOpsEntities())
{
var assignedCar = (from car in myEntities.Vehicles
where (car.CarNum == carNum)
select car).FirstOrDefault();
if (assignedCar != null && newRide != null)
{
Ride lastRide = assignedCar.Rides.LastOrDefault(); //HERE IS WHERE I NEED TO LOAD THE MOST RECENT 'RIDE' FOR THIS CAR, IS THIS CORRECT???
if (lastRide != null)
{
lastRide.Status = "Completed";
assignedCar.numRides = assignedCar.numRides + 1;
lastRide.TimeDroppedOff = DateTime.Now;
TimeSpan duration = (lastRide.TimeDroppedOff - lastRide.TimeDispatched).Value;
lastRide.ServiceTime = duration;
if (assignedCar.AvgRideTime == null)
{
assignedCar.AvgRideTime = duration;
}
else
{
assignedCar.AvgRideTime = TimeSpan.FromSeconds(( ((TimeSpan)assignedCar.AvgRideTime).Seconds + duration.Seconds) / assignedCar.numRides);
}
}
assignedCar.Status = "EnRoute";
assignedCar.CurrPassengers = newRide.NumPatrons;
assignedCar.StartAdd = newRide.PickupAddress;
assignedCar.EndAdd = newRide.DropoffAddress;
//HERE IS WHERE I NEED TO ADD THE 'newRide' OBJECT TO THE LIST OF RIDES IN THE 'assignedCar' ..SYNTAX???
newRide.TimeDispatched = DateTime.Now;
newRide.AssignedCar = carNum;
newRide.Status = "EnRoute";
myEntities.SaveChanges();
SelectCarUP.DataBind();
SelectCarUP.Update();
}
}
}
For:
// HERE IS WHERE I NEED TO LOAD THE MOST RECENT 'RIDE' FOR THIS CAR, IS
// THIS CORRECT???
Ride lastRide = assignedCar.Rides.LastOrDefault();
Use:
Ride lastRide = assignedCar.Rides
.OrderByDescending(r => r.TimeDispatched)
.FirstOrDefault();
...and for:
// HERE IS WHERE I NEED TO ADD THE 'newRide' OBJECT TO THE LIST OF RIDES
// IN THE 'assignedCar' ..SYNTAX???
...your Vehicle entity has a Rides collection property already according to your model diagram, so you should just be able to say:
assignedCar.Rides.Add(newRide);
Finally - and purely as a matter of personal taste - instead of:
var assignedCar = (from car in myEntities.Vehicles
where (car.CarNum == carNum)
select car).FirstOrDefault();
I'd use:
var assignedCar = myEntities.Vehicles
.FirstOrDefault(car => car.CarNum == carNum);
In my opinion, the following articles are good places to start:
EF 4.1 Code First Walkthrough
Code First Relationships Fluent API. See Blog and Post entities, where Blog has a one-to-many
relationship with Posts.

Categories

Resources