Parallel class in C# - c#-4.0

i am copying one object to another using for loop which is dependent on noOFResults. I replaced Foreach loop by Parallel.For to increase the performance but the same cause major performance degrade. So I want to understand what is the cause of this ??
int resultCount = 0;
var apiSearchResults = new PS_HotelSearchResult[results.Count];
foreach (BE_HotelSearchResult result in results)
{
apiSearchResults[resultCount] = new PS_HotelSearchResult();
#region Fields of First Search
apiSearchResults[resultCount].RateType = (PS_RateType)result.RateType;
apiSearchResults[resultCount].HotelCode = result.HotelCode;
apiSearchResults[resultCount].Discount = result.AmountBeforeDiscountInSupplierCurr -
result.AmountAfterTaxInSupplierCurr;
apiSearchResults[resultCount].AmountAfterTax = result.AmountAfterTaxInSupplierCurr;
apiSearchResults[resultCount].AmountBeforeTax = result.AmountBeforeTaxInSupplierCurr;
apiSearchResults[resultCount].Currency = result.CurrencySupplier;
apiSearchResults[resultCount].IsUniversalApiResult = true;
if (result.Price != null)
{
apiSearchResults[resultCount].TotalGP = result.Price.TotalGP;
}
#endregion
#region Fields for Room
if (!Equals(result.RoomDetails, null))
{
int roomCount = 0;
apiSearchResults[resultCount].RoomDetails =
new PS_HotelRoomsDetails[result.RoomDetails.Length];
foreach (BE_HotelRoomsDetails roomDetail in result.RoomDetails)
{
if (roomDetail.CancellationPolicies == null)
{
throw new BusinessServiceException("HotelPrice.GetPrice - CancellationPolicies SHOULD NOT BE Null for rooms");
}
apiSearchResults[resultCount].RoomDetails[roomCount] = new PS_HotelRoomsDetails
{
SequenceNo = roomDetail.SequenceNo,
#region ExtraGuestCharge and ChildCharges
// Multiplied by number of nights becuase its a day wise price and we are setting it roomwise
SellExtraGuestCharges = roomDetail.SellExtraGuestCharges,
PubExtraGuestCharges = roomDetail.PubExtraGuestCharges,
ChildCharges = roomDetail.ChildCharges,
SellChildCharges = roomDetail.SellChildCharges,
#endregion
#region Discount and Tax
Discount = roomDetail.Discount,
TotalTax = roomDetail.TotalTax,
#endregion
};
int k = 0;
#region DayWiseRate
if (!Equals(roomDetail.Rates, null))
{
apiSearchResults[resultCount].RoomDetails[roomCount].Rates =
new PS_RoomRates[roomDetail.Rates.Length];
foreach (BE_RoomRates rate in roomDetail.Rates)
{
apiSearchResults[resultCount].RoomDetails[roomCount].Rates[k] = new PS_RoomRates
{
Amount = rate.Amount,
//Pricing is wrong
//SellingFare = rate.SellingFare
};
k++;
}
}
#endregion
k = 0;
#region Additional Charges
if (!Equals(roomDetail.AdditionalCharges, null))
{
apiSearchResults[resultCount].RoomDetails[roomCount].AdditionalCharges =
new PS_AdditionalCharges[roomDetail.AdditionalCharges.Count];
foreach (
BE_AdditionalCharges additionalCharge in
roomDetail.AdditionalCharges)
{
apiSearchResults[resultCount].RoomDetails[roomCount].AdditionalCharges[k] = new PS_AdditionalCharges
{
Charge = additionalCharge.Charge,
IncludedInTotal = additionalCharge.IncludedInTotal
};
k++;
}
}
#endregion
#region Price and Price Component
apiSearchResults[resultCount].RoomDetails[roomCount].Price = new HotelPriceAccounts();
if (!Equals(roomDetail.Price, null))
{
apiSearchResults[resultCount].RoomDetails[roomCount].Price.Discount = roomDetail.Price.Discount;
apiSearchResults[resultCount].RoomDetails[roomCount].Price.PublishedFare = roomDetail.Price.PublishedFare;
apiSearchResults[resultCount].RoomDetails[roomCount].Price.Tax = roomDetail.Price.Tax;
apiSearchResults[resultCount].RoomDetails[roomCount].Price.OtherCharge = roomDetail.Price.OtherCharges;
apiSearchResults[resultCount].RoomDetails[roomCount].Price.TotalGP = roomDetail.Price.TotalGP;
apiSearchResults[resultCount].RoomDetails[roomCount].Price.IsGPEnabled = roomDetail.Price.IsGPEnabled;
apiSearchResults[resultCount].RoomDetails[roomCount].Price.AgentMarkUpType =
(AgentMarkUpType)roomDetail.Price.AgentMarkUpType;
apiSearchResults[resultCount].RoomDetails[roomCount].Price.PriceId = roomDetail.Price.PriceId;
}
#endregion
roomCount++;
}
}

There are no for loops in the code, just foreach loops.
Do not expect loops to be automatically faster when using Parallel.For.
Especially when iterations have effect on the outer scope, the iterations can hardly be run in parallel. So all you are adding is overhead to split the iterations across tasks.
The outer scope is affected by changing Amount. k and apiSearchResults inside of the loops, just to name a few.

Related

Add an additional line on the grid

I am looking for help, I hope I can solve this problem.
I've created a new screen and I'm filtering all the Revalue Accounts information.
With this screen, what I want to do is insert and at the same time add an additional new line within the grid.
Here is my new created screen and the button that inserts GLTran
I am attaching an image where I want the line to be added at insert time
Here I share code that I have and it does not work for the additional line.
private void CreateDNGL(Batch batch)
{
var graph = PXGraph.CreateInstance<JournalEntry>();
if (graph.BatchModule.Current == null)
{
Batch cmbatch = new Batch();
cmbatch.BranchID = batch.BranchID;
cmbatch.Module = batch.Module;
cmbatch.Status = "U";
cmbatch.AutoReverse = true;
cmbatch.Released = true;
cmbatch.Hold = false;
cmbatch.CuryDebitTotal = batch.CuryDebitTotal;
cmbatch.CuryCreditTotal = batch.CuryCreditTotal;
cmbatch.FinPeriodID = batch.FinPeriodID;
cmbatch.CuryID = batch.CuryID;
cmbatch.CuryInfoID = batch.CuryInfoID;
cmbatch.DebitTotal = batch.DebitTotal;
cmbatch.CreditTotal = batch.CreditTotal;
cmbatch.Description = "Head new insert";
cmbatch = graph.BatchModule.Insert(cmbatch);
}
foreach (GLTran item in PXSelect<GLTran,
Where<GLTran.module, Equal<Required<GLTran.module>>,
And<GLTran.batchNbr, Equal<Required<GLTran.batchNbr>>>>>.Select(this, batch.Module, batch.BatchNbr))
{
GLTran tran = new GLTran();
tran.SummPost = item.SummPost;
tran.ZeroPost = false;
tran.DebitAmt = item.DebitAmt;
tran.CreditAmt = item.CreditAmt;
tran.CuryDebitAmt = item.CuryDebitAmt;
tran.CuryCreditAmt = item.CuryCreditAmt;
tran.AccountID = item.AccountID;
tran.SubID = item.SubID;
tran.LineNbr = item.LineNbr;
tran.LedgerID = item.LedgerID;
tran.TranType = item.TranType;
tran.TranClass = item.TranClass;
tran.RefNbr = string.Empty;
tran.FinPeriodID = item.FinPeriodID;
tran.TranDesc = "Test detail";
tran.Released = true;
tran.ReferenceID = item.ReferenceID;
tran = graph.GLTranModuleBatNbr.Insert(tran);
Account account = PXSelect<Account, Where<Account.accountID,
Equal<Required<Account.accountID>>>>.Select(graph, item.AccountID);
xLocEquivalAcct equivalAcct = PXSelect<xLocEquivalAcct, Where<xLocEquivalAcct.acctCD,
Equal<Required<xLocEquivalAcct.acctCD>>>>.Select(graph, account.AccountCD);
if (equivalAcct != null)
{
/*here is added for an additional line*/
var glTran = graph.GLTranModuleBatNbr.Insert();
graph.GLTranModuleBatNbr.SetValueExt<GLTran.accountID>(glTran, 343567);
graph.GLTranModuleBatNbr.SetValueExt<GLTran.subID>(glTran, 281);
glTran.TranDesc = "add extra line";
if (item.DebitAmt != 0m && item.CreditAmt == 0m)
{
if (batch.Module == BatchModule.CM)
{
graph.GLTranModuleBatNbr.SetValueExt<GLTran.curyDebitAmt>(glTran, item.CuryDebitAmt);
graph.GLTranModuleBatNbr.SetValueExt<GLTran.debitAmt>(glTran, item.DebitAmt);
}
}
if (item.CreditAmt != 0m && item.DebitAmt == 0m)
{
if (batch.Module == BatchModule.CM)
{
graph.GLTranModuleBatNbr.SetValueExt<GLTran.curyCreditAmt>(glTran, item.CuryCreditAmt);
graph.GLTranModuleBatNbr.SetValueExt<GLTran.creditAmt>(glTran, item.CreditAmt);
}
}
glTran = graph.GLTranModuleBatNbr.Update(glTran);
}
}
graph.Save.Press();
}
I hope I was clear with my question.
This code will create a copy of the originating batch and insert additional lines.
#Warning Your original code was attempting to create a batch that was already released but unposted. I can update my answer to match your requirement but this will break Acumatica work-flow.
Please find code example below :
public class JournalEntryExtension : PXGraphExtension<JournalEntry>
{
public PXAction<Batch> CopyCreate;
//CommitChanges being set to false allows the graph to not be considered dirty when there are errors that we manually show on screen. Case #207998
[PXButton(CommitChanges = false)]
[PXUIField(DisplayName = "Copy Create", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update, Enabled = true)]
protected virtual IEnumerable copyCreate(PXAdapter pxAdapter)
{
if (Base.BatchModule.Current != null)
{
if (Base.IsDirty)
{
Base.BatchModule.Ask("You must discard your unsaved changes to be able to press this button.", MessageButtons.OK);
}
else
{
Batch batch = Base.BatchModule.Current;
PXLongOperation.StartOperation(this, () => CreateDNGL(batch));
}
}
return pxAdapter.Get();
}
private static void CreateDNGL(Batch batch)
{
JournalEntry graph = PXGraph.CreateInstance<JournalEntry>();
Batch newBatch = PXCache<Batch>.CreateCopy(batch);
newBatch.NoteID = null;
newBatch.Description = "Test header";
newBatch = graph.BatchModule.Insert(newBatch);
GLTran newTran;
foreach (GLTran tran in PXSelectReadonly<GLTran,
Where<GLTran.module, Equal<Required<GLTran.module>>,
And<GLTran.batchNbr, Equal<Required<GLTran.batchNbr>>>>>.Select(graph, batch.Module, batch.BatchNbr))
{
newTran = PXCache<GLTran>.CreateCopy(tran);
newTran.Module = null;
newTran.BatchNbr = null;
newTran.NoteID = null;
newTran.TranDesc = "Test detail";
newTran = graph.GLTranModuleBatNbr.Insert(newTran);
}
if (true)
{
newTran = graph.GLTranModuleBatNbr.Insert();
newTran.AccountID = 1190;
newTran.SubID = 467;
newTran.CuryDebitAmt = 1000;
newTran.TranDesc = "Additional Line 1";
newTran = graph.GLTranModuleBatNbr.Update(newTran);
newTran = graph.GLTranModuleBatNbr.Insert();
newTran.AccountID = 1190;
newTran.SubID = 467;
newTran.CuryCreditAmt = 1000;
newTran.TranDesc = "Additional Line 2";
newTran = graph.GLTranModuleBatNbr.Update(newTran);
}
graph.Save.Press();
}
}
Original Batch :
New Batch :

Provide data lookup for PXSelector

I need advice either to convert the SQL to BQL or set the Resultset manipulated by C# code to the PXSelector.
I need to customize the AR Invoice and add 2 custom fields to record the COGS GL account and sub account for the inter company client when the inter company enter this invoice line as a bill. This custom field need to look up all sub accounts that is restricted to this Client's Branch ID and GL account. Basically all system's sub account lookup take care of the restriction group but for the custom fields; a custom PXSelector need to be written for this. Below is the SQL that supplies the require sub accounts but I need to know how to make the SQL query works in Acumatica
-- SQL for the required data
DECLARE #GLAccountCD nvarchar(10) = 'COGS'
DECLARE #BranchCD nvarchar(30) = 'PurchaseBranch'
SELECT *
FROM Sub
where (((CAST(Sub.groupmask as int) & CAST((SELECT GroupMask FROM Account WHERE AccountCD = #GLAccountCD AND CompanyID = 3 AND DeletedDatabaseRecord = 0) AS int)) > 1
AND (CAST(Sub.groupmask as int) & CAST((SELECT GroupMask FROM Branch WHERE BranchCD = #BranchCD AND CompanyID = 3 AND DeletedDatabaseRecord = 0) AS int)) > 1)
OR (Sub.GroupMask = 0 AND Sub.DeletedDatabaseRecord = 0))
AND CompanyID = 3
ORDER BY SubCD
--The below PXSelector provide all sub accounts regard of restriction group,
--I need the PXSelector to use the above SQL Query result
#region UsrAPBIllGLSubAccID
[PXDBInt]
[PXUIField(DisplayName="Bill COGS SubAccount")]
[PXSelector(typeof(Search<Sub.subID, Where<Sub.active, Equal<True>>, OrderBy<Desc<Sub.subCD>>>),
new Type[] {typeof(Sub.subCD),
typeof(Sub.description)},
SubstituteKey = typeof(Sub.subCD)
)]
public virtual int? UsrAPBIllGLSubAccID { get; set; }
public abstract class usrAPBIllGLSubAccID : IBqlField { }
#endregion
I think that would be achievable using the Match BQL clause.
GLAccess.cs file has BQL queries to restrict accounts based on Sub and Branch group mask using Match clause, this would be a good place to investigate:
public PXSelect<Sub> Sub;
protected virtual IEnumerable sub(
)
{
if (Group.Current != null && !String.IsNullOrEmpty(Group.Current.GroupName))
{
bool inserted = (Group.Cache.GetStatus(Group.Current) == PXEntryStatus.Inserted);
foreach (Sub item in PXSelect<Sub,
Where2<Match<Current<PX.SM.RelationGroup.groupName>>,
Or2<Match<Required<Sub.groupMask>>, Or<Sub.groupMask, IsNull>>>>
.Select(this, new byte[0]))
{
if (!inserted || item.Included == true)
{
Sub.Current = item;
yield return item;
}
else if (item.GroupMask != null)
{
PX.SM.RelationGroup group = Group.Current;
bool anyGroup = false;
for (int i = 0; i < item.GroupMask.Length && i < group.GroupMask.Length; i++)
{
if (group.GroupMask[i] != 0x00 && (item.GroupMask[i] & group.GroupMask[i]) == group.GroupMask[i])
{
Sub.Current = item;
yield return item;
}
anyGroup |= item.GroupMask[i] != 0x00;
}
if (!anyGroup)
{
Sub.Current = item;
yield return item;
}
}
}
}
else
{
yield break;
}
}
public PXSelect<Branch> Branch;
protected virtual IEnumerable branch(
)
{
if (Group.Current != null && !String.IsNullOrEmpty(Group.Current.GroupName))
{
bool inserted = (Group.Cache.GetStatus(Group.Current) == PXEntryStatus.Inserted);
foreach (Branch item in PXSelect<Branch,
Where2<Match<Current<PX.SM.RelationGroup.groupName>>,
Or<Match<Required<Branch.groupMask>>>>>
.Select(this, new byte[0]))
{
if (!inserted)
{
Branch.Current = item;
yield return item;
}
else if (item.GroupMask != null)
{
PX.SM.RelationGroup group = Group.Current;
bool anyGroup = false;
for (int i = 0; i < item.GroupMask.Length && i < group.GroupMask.Length; i++)
{
if (group.GroupMask[i] != 0x00 && (item.GroupMask[i] & group.GroupMask[i]) == group.GroupMask[i])
{
Branch.Current = item;
yield return item;
}
anyGroup |= item.GroupMask[i] != 0x00;
}
if (!anyGroup)
{
Branch.Current = item;
yield return item;
}
}
}
}
else
{
yield break;
}
}

Changes in cache saved in database before calling Persist()

I have created a new grid with Case classes in Contract Template screen which updates case classes for particular Contract Template. There is a checkbox for every case class in the grid and when I check/Uncheck, RowUpdatedEventHandler is triggered and I am updating the contents of Cache.
I have overridden Persist() to save the contents of the cache in Database. But before Persist() is being called the changes are saved in the database and the cache is cleared.Please, Someone help me with this
protected void CRCaseClass_RowUpdated(PXCache sender, PXRowUpdatedEventArgs
e)
{
CRCaseClass newrow = (CRCaseClass)e.Row;
CRCaseClass oldrow = (CRCaseClass)e.OldRow;
ContractTemplate row = contracts.Current;
CaseContract c = new CaseContract();
CRCaseClassExt newrow_ext =
PXCache<CRCaseClass>.GetExtension<CRCaseClassExt>(newrow);
CRCaseClassExt oldrow_ext =
PXCache<CRCaseClass>.GetExtension<CRCaseClassExt>(oldrow);
c.CaseClassID = newrow.CaseClassID;
c.ContractID = row.ContractID;
c.Active = newrow_ext.Check.Value;
caseContract.Insert(c);
}
[PXOverride]
public void Persist()
{
bool c = caseContract.Cache.IsInsertedUpdatedDeleted;
CaseContract cc = null;
IEnumerable cacheRecords = caseContract.Cache.Inserted;
List<CaseContract> recordsToBePersisted = new List<CaseContract>();
ContractTemplate row = contracts.Current;
foreach (CaseContract cr in cacheRecords)
{
PXResultset<CaseContract> v = PXSelect<CaseContract, Where<CaseContract.contractID,
Equal<Required<ContractTemplate.contractID>>, And<CaseContract.caseClassID,
Equal<Required<CRCaseClass.caseClassID>>>>>.Select(Base, row.ContractID, cr.CaseClassID);
if (v.Count != 0 && v.Count == 1)
{
cc = v.GetEnumerator().Current;
cc.Active = cr.Active;
}
else if (v.Count == 0)
{
cc = new CaseContract();
cc.CaseClassID = cr.CaseClassID;
cc.ContractID = cr.ContractID;
cc.Active = cr.Active;
}
else {
//Error Logic
}
recordsToBePersisted.Add(cc);
}
//clean all cache
//insert all values from recordsToBePersisted
caseContract.Cache.Clear();
foreach (CaseContract i in recordsToBePersisted) {
caseContract.Insert(i);
}
Base.Persist();
The Acumatica way to override virtual methods in BLC extensions is slightly different from what you get used to with the .Net framework. Below is the updated version of your code, that should resolve the issue with empty caches. For more details on this topic, please refer to the Acumatica Customization Guide
[PXOverride]
public void Persist(Action del)
{
bool c = caseContract.Cache.IsInsertedUpdatedDeleted;
CaseContract cc = null;
IEnumerable cacheRecords = caseContract.Cache.Inserted;
List<CaseContract> recordsToBePersisted = new List<CaseContract>();
ContractTemplate row = contracts.Current;
foreach (CaseContract cr in cacheRecords)
{
PXResultset<CaseContract> v = PXSelect<CaseContract, Where<CaseContract.contractID,
Equal<Required<ContractTemplate.contractID>>, And<CaseContract.caseClassID,
Equal<Required<CRCaseClass.caseClassID>>>>>.Select(Base, row.ContractID, cr.CaseClassID);
if (v.Count != 0 && v.Count == 1)
{
cc = v.GetEnumerator().Current;
cc.Active = cr.Active;
}
else if (v.Count == 0)
{
cc = new CaseContract();
cc.CaseClassID = cr.CaseClassID;
cc.ContractID = cr.ContractID;
cc.Active = cr.Active;
}
else
{
//Error Logic
}
recordsToBePersisted.Add(cc);
}
//clean all cache
//insert all values from recordsToBePersisted
caseContract.Cache.Clear();
foreach (CaseContract i in recordsToBePersisted)
{
caseContract.Insert(i);
}
del();
}

Getting a random UserProfile In SharePoint 2010

I am trying to retrieve a random number of users from the UserProfileManager.
But I am encountering errors when deploying to the live servers. I can't seem to see what is causing the error. My code is below:
for (int i = 0; i < NumberOfUserLimit; i++)
{
UserProfile up = profileManager.GetUserProfile(random.Next(1, NumberOfUserLimit));
if (up["FirstName"] != null && up["FirstName"].Value != null && !String.IsNullOrEmpty(up["FirstName"].Value.ToString()))
{
DataRow drUserProfile;
drUserProfile = dtUserProfile.NewRow();
drUserProfile["DisplayName"] = up.DisplayName;
drUserProfile["FirstName"] = up["FirstName"].Value;
drUserProfile["LastName"] = up["LastName"].Value;
drUserProfile["Department"] = up["Department"].Value;
drUserProfile["Location"] = up["SPS-Location"].Value;
drUserProfile["HireDate"] = up["SPS-HireDate"].Value;
drUserProfile["ContactNumber"] = up["Office"].Value;
if (up["PictureURL"] != null && up["PictureURL"].Value != null && !String.IsNullOrEmpty(up["PictureURL"].Value.ToString()))
{
string cleanAccountName = up["AccountName"].Value.ToString().Replace(#"\", "_");
string pictureUrl = String.Format("https://my.someintranet.com/User Photos/Profile Pictures/{0}_MThumb.jpg", cleanAccountName);
drUserProfile["Image"] = pictureUrl;
}
else
{
drUserProfile["Image"] = "~/_layouts/images/O14_person_placeHolder_96.png";
}
drUserProfile["MySiteUrl"] = up.PublicUrl;
dtUserProfile.Rows.Add(drUserProfile);
}
}
My code works when I apply a simple foreach to my code above instead of the "for loop":
foreach (UserProfile up in profileManager)
Which proves I can return userprofiles.
Any help is appreciated.
profileManager.GetUserProfile(long recordId)
expects a recordId from userprofile table. It is not an index, so you cannot use "random".
If you want to check RecordId, you can take a look at SQL tables of ProfileDB. Table "UserProfile_Full" has MasterRecordId column. Your parameter in GetUserProfile has to match of the user profile's MasterRecordId.
you can use the following code to get your random profiles:
IEnumerator profiles = profileManager.GetEnumerator();
int index = new Random().Next(1, 100);
while (index >= 0 && profiles.MoveNext())
index--;
UserProfile currentProfile = (UserProfile)profiles.Current
Code that handles Random better
public class TestClass
{
private random = new Random();
private long totalNumberOfProfiles; //ProfileManager.Count not always returns count correctly
public TestClass()
{
//this does not have to be in constructor but point is to have it cached (reasonably)
IEnumerator profiles = profileManager.GetEnumerator();
long counter = 0;
while (profiles.MoveNext())
counter++;
this.totalNumberOfProfiles = counter;
}
public fillInDataSet()
{
//something is here...
IEnumerator profiles = profileManager.GetEnumerator();
int index = random.Next(1, totalNumberOfProfiles);
while (index >= 0 && profiles.MoveNext())
index--;
UserProfile currentProfile = (UserProfile)profiles.Current
//something is here...
}
}

Sharepoint 2010 custom webpart paging

I am trying to implement simple paging on my sharepoint webpart. I have a single news articles list which has some simple columns. I want to be able to have then five on a page and with some numerical paging at the bottom. I have gone through the net trying to understand splistitemcollectionposition but with no luck. If anyone can help please can you give me a simple code example or some guidanc
Many thanks
Chris
I would suggest using SPDataSource and a SPGridView, together they will implement paging and many other cool features with minimal or no code.
Use this a a guide for some of the classes/methods/properties you might need to use to get paging to work. Be aware that this code does not compile, i have just pulled together various code snippets that i have in my own list results framework, which includes paging, sorting, grouping and caching. It should be enough to get you started though.
public class PagedListResults : System.Web.UI.WebControls.WebParts.WebPart {
protected SPPagedGridView oGrid;
protected override void CreateChildControls() {
this.oGrid = new SPPagedGridView();
oGrid.AllowPaging = true;
oGrid.PageIndexChanging += new GridViewPageEventHandler(oGrid_PageIndexChanging);
oGrid.PagerTemplate = null; // Must be called after Controls.Add(oGrid)
oGrid.PagerSettings.Mode = PagerButtons.NumericFirstLast;
oGrid.PagerSettings.PageButtonCount = 3;
oGrid.PagerSettings.Position = PagerPosition.TopAndBottom;
base.CreateChildControls();
}
public override void DataBind() {
base.DataBind();
SPQuery q = new SPQuery();
q.RowLimit = (uint)info.PageSize;
if (!string.IsNullOrEmpty(info.PagingInfoData)) {
SPListItemCollectionPosition pos = new SPListItemCollectionPosition(info.PagingInfoData);
q.ListItemCollectionPosition = pos;
} else {
//1st page, dont need a position, and using a position breaks things
}
q.Query = info.Caml;
SPListItemCollection items = SPContext.Current.List.GetItems(q);
FilterInfo info = null;
string tmp = "<View></View>";
tmp = tmp.Replace("<View><Query>", string.Empty);
tmp = tmp.Replace("</Query></View>", string.Empty);
info.Caml = tmp;
info.PagingInfoData = string.Empty;
info.CurrentPage = oGrid.CurrentPageIndex;
info.PageSize = oGrid.PageSize;
if (oGrid.PageIndex == 0 || oGrid.CurrentPageIndex == 0) {
//do nothing
} else {
StringBuilder value = new StringBuilder();
value.Append("Paged=TRUE");
value.AppendFormat("&p_ID={0}", ViewState[KEY_PagingPrefix + "ID:" + oGrid.PageIndex]);
info.PagingInfoData = value.ToString();
}
int pagecount = (int)Math.Ceiling(items.Count / (double)oGrid.PageSize);
for (int i = 1; i < pagecount; i++) { //not always ascending index numbers
ResultItem item = items[(i * oGrid.PageSize) - 1];
ViewState[KEY_PagingPrefix + "ID:" + i] = item.ID;
}
oGrid.VirtualCount = items.Count;
DateTime time3 = DateTime.Now;
DataTable table = new DataTable("Data");
DataBindListData(table, items);
this.oGrid.DataSource = table;
this.oGrid.DataBind();
this.oGrid.PageIndex = oGrid.CurrentPageIndex; //need to reset this after DataBind
}
void oGrid_PageIndexChanging(object sender, GridViewPageEventArgs e) {
oGrid.PageIndex = e.NewPageIndex;
oGrid.CurrentPageIndex = oGrid.PageIndex;
}
}
public class FilterInfo {
public string Caml;
public string PagingInfoData;
public int CurrentPage;
public int PageSize;
}
public class SPPagedGridView : SPGridView {
protected override void InitializePager(GridViewRow row, int columnSpan, PagedDataSource pagedDataSource) {
pagedDataSource.AllowCustomPaging = true;
pagedDataSource.VirtualCount = virtualcount;
pagedDataSource.CurrentPageIndex = currentpageindex;
base.InitializePager(row, columnSpan, pagedDataSource);
}
private int virtualcount = 0;
public int VirtualCount {
get { return virtualcount; }
set { virtualcount = value; }
}
private int currentpageindex = 0;
public int CurrentPageIndex {
get { return currentpageindex; }
set { currentpageindex = value; }
}
}
check out my post on how to page using SPListItemCollectionPosition, I did a component to page over lists, maybe it can help -> http://hveiras.wordpress.com/2011/11/07/listpagert-using-splistitemcollectionposition/

Resources