Checking if exist in List - c#

I created a method where i take a random row from ma database and put it into new List, if the method will be used again, it will check if the random row was selected before and chose another one, like drawing without repetition.The program compile, but dont work. Can anyone tell me what i am doing wrong?
TABUEntities baza = new TABUEntities();
IList AlreadyChosen = new List<IList>();
public List<HASLA> RandomWords()
{
List<HASLA> dane = baza.HASLA.OrderBy(x => Guid.NewGuid()).Take(1).ToList();
if (AlreadyChosen.Contains(dane))
{
RandomWords();
}
AlreadyChosen.Add(dane);
return dane;
}

if (AlreadyChosen.Any(a=>a.SomeUniqueProperty == dane.SomeUniqueProperty))
You have to search by some unique property like Id to make sure you can find the object. Also if you want to use Contains then you will have to implement and override the IComparable interface and methods, or pass a custom comparer.

Try this
TABUEntities baza = new TABUEntities();
List<HASLA> AlreadyChosen = new List<HASLA>();
public List<HASLA> RandomWords()
{
List<HASLA> rw = new List<HASLA>();
rw.addRange(AlreadyChosen);
HASLA selectedObj = baza.HASLA.Where(y => !AlreadyChosen.Contains(y)).OrderBy(x => Guid.NewGuid()).Take(1).FirstOrDefault();
if ((selectedObj == null)) {
return rw;
} else {
if (AlreadyChosen.Contains(selectedObj)) {
return RandomWords();
} else {
AlreadyChosen.add(selectedObj);
return RandomWords();
}
}
}

Related

Twincat Ads Reactive weird Handle behaviour

I'm working with TwincatAds.Reactive 6.0.190 in .NET 6 WPF Desktop application.
I'm also using MVVM pattern.
My goal is to create a Class that is going to observe for a PLC Variable changes, collect those variables to a dictionary, and later on use those values in the ViewModel.
Here's the method where I'm attaching the notification and action where I'm handling the notification.
public void AttachNotification(IEnumerable<(string key, Type type)> Symbols)
{
_observerValueNotification = Observer.Create<ValueNotification>(val =>
{
// Does handle really start from 2?
var handle = val.Handle;
if (val.UserData is object[] objects)
{
string tag = objects[handle - 2].ToString();
if (!_values.Any(x => x.Key == tag))
_values.Add(new SymbolModel { Key = tag, Value = val.Value });
else
{
var symbol = _values.First(x => x.Key == tag);
symbol.Value = val.Value;
}
}
ValuesChanged?.Invoke(_values);
});
if (_plcWrapper.AdsClient != null)
{
// Get Symbols from SymbolLoader
List<AnySymbolSpecifier> list = new();
List<string> userData = new();
foreach (var (key, type) in Symbols)
{
list.Add(new AnySymbolSpecifier(key, new AnyTypeSpecifier(type)));
userData.Add(key);
}
_subscription2 = _plcWrapper.AdsClient.WhenNotificationEx(list, NotificationSettings.ImmediatelyOnChange, userData.ToArray())
.Subscribe(_observerValueNotification);
}
}
I'm using ValueNotification simply because, I'd like to use this pattern also for complex PLC Variables like Structs.
As You can see, in the WhenNotificationEx method I'm using UserData[] to provide some sort of identification of what Variable has changed when handling the change.
My idea was to use Handle property from ValueNotification as an indexer in UserData[] to identify what variable I'm dealing with, but for some reason Handle starts from 2.
My question is, is it expected behaviour, does the Handle value really always start from 2?
I've decided that relying on the Handle being index in the UserData array is quite unpredictable as Handle is being created by the Twincat Ads server.
Solved the issue by creating own extension method to the WhenNotificationEx. Turned out IDisposableHandleBag has exactly what I was looking for, which is SourceResultHandles property, where AnySymbolSpecifier and ResultHandle are both stored!
Here's created extension method
public static Dictionary<string, uint> Handles { get; private set; } = new();
public static IObservable<ValueNotification> WhenNotificationWithHandle(this IAdsConnection connection, IList<AnySymbolSpecifier> symbols, NotificationSettings settings)
{
IAdsConnection connection2 = connection;
IList<AnySymbolSpecifier> symbols2 = symbols;
NotificationSettings settings2 = settings;
if (connection2 == null)
{
throw new ArgumentNullException("connection");
}
if (symbols2 == null)
{
throw new ArgumentNullException("symbols");
}
if (symbols2.Count == 0)
{
throw new ArgumentOutOfRangeException("symbols", "Symbol list is empty!");
}
IDisposableHandleBag<AnySymbolSpecifier> bag = null;
EventLoopScheduler scheduler = new EventLoopScheduler();
IObservable<int> whenSymbolChangeObserver = connection2.WhenSymbolVersionChanges(scheduler);
IDisposable whenSymbolChanges = null;
Action<EventHandler<AdsNotificationExEventArgs>> addHandler = delegate (EventHandler<AdsNotificationExEventArgs> h)
{
connection2.AdsNotificationEx += h;
bag = ((IAdsHandleCacheProvider)connection2).CreateNotificationExHandleBag(symbols2, relaxSubErrors: false, settings2, null);
bag.CreateHandles();
// Collect Handles
Handles.Clear();
foreach (var item in bag.SourceResultHandles)
Handles.Add(item.source.InstancePath, item.result.Handle);
whenSymbolChanges = whenSymbolChangeObserver.Subscribe((Action<int>)delegate
{
bag.CreateHandles();
Handles.Clear();
foreach (var item in bag.SourceResultHandles)
Handles.Add(item.source.InstancePath, item.result.Handle);
}, (Action<Exception>)delegate
{
TcTraceSource traceAds = AdsModule.TraceAds;
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(101, 1);
defaultInterpolatedStringHandler.AppendLiteral("The AdsServer '");
defaultInterpolatedStringHandler.AppendFormatted(connection2.Address);
defaultInterpolatedStringHandler.AppendLiteral("' doesn't support SymbolVersionChanged Notifications! Handle recreation is not active!");
traceAds.TraceInformation(defaultInterpolatedStringHandler.ToStringAndClear());
});
};
Action<EventHandler<AdsNotificationExEventArgs>> removeHandler = delegate (EventHandler<AdsNotificationExEventArgs> h)
{
if (whenSymbolChanges != null)
{
whenSymbolChanges.Dispose();
}
scheduler.Dispose();
if (bag != null)
{
bag.Dispose();
bag = null;
Handles.Clear();
}
connection2.AdsNotificationEx -= h;
};
return from ev in Observable.FromEventPattern<EventHandler<AdsNotificationExEventArgs>, AdsNotificationExEventArgs>(addHandler, removeHandler)
where bag.Contains(ev.EventArgs.Handle)
select new ValueNotification(ev.EventArgs, ev.EventArgs.Value);
}

How to remove items from Ilist

I have an IList , I also have a method which checks if the item is already in list and if it is I need it to be deleted/ removed and add again.
private PurchaseItemViewModel CheckSessionPurchaseItemViewModel(long purchaseLevelId)
{
bool itemFound = false;
PurchaseItemViewModel purItem = new PurchaseItemViewModel();
foreach (var item in UserSession.UserDataPurchaseItems)
{
if (item.PurchaseLevelId == purchaseLevelId)
{
itemFound = true;
purItem.Note = item.Note;
purItem.PurchaseAmount = item.PurchaseAmount;
purItem.PurchaseLevelId = item.PurchaseLevelId;
}
}
if (itemFound)
{
return purItem;
}
return null;
}
If it the above method finds the purchase item then it returns an object else null.
IList<PurchaseItemViewModel> purchaseSessionList = UserSession.UserDataPurchaseItems;
PurchaseItemViewModel pItem = CheckSessionPurchaseItemViewModel(levelId);
if(pItem != null)
{
purchaseSessionList.Remove(item);
}
So the issue is with the below line it is not removing the item , it does not even error.
**purchaseSessionList.Remove(item);**
Use this code for removing:
if(pItem != null) purchaseSessionList.Remove( purchaseSessionList.SingleOrDefault( s => s.PurchaseLevelId== levelId) );
IMHO you don't need to create pItem, would be enough to return false or true or item primary key.

Performance issue when performing operations on entity objects

Im facing performance issue in below code in multiple foreach loops. First im getting a list of ReturnDetails and then based on detail id get the HandlingInfo object. Then based on value of action, update the ReturnsDetail Object again.
It take more than a minute for loading 3000 records of ReturnsDetail. While debugging locally, it runs for infinite amount of time.
Please let me know in anyway i can refactor this code .
Thanks for your help.
lstReturnsDetail = dcReturnsService.GetReturnDetailsInfo(header_id);
List<HandlingInfo> lstHandlingInfo = null;
foreach (ReturnsDetail oReturnsDetail in lstReturnsDetail)
{
using (DCReturns_Entities entities = new DCReturns_Entities())
{
lstHandlingInfo = entities.HandlingInfoes.Where(f => f.detail_id == oReturnsDetail.id).ToList();
if(lstHandlingInfo != null)
{
foreach (HandlingInfo oHandlingInfo in lstHandlingInfo)
{
if (oHandlingInfo.action == "DST")
{
oReturnsDetail.destroy += Convert.ToInt32(oHandlingInfo.qty);
}
else if (oHandlingInfo.action == "SHP")
{
oReturnsDetail.to_shop += Convert.ToInt32(oHandlingInfo.qty);
}
else if (oHandlingInfo.action == "RBX")
{
oReturnsDetail.in_stock += Convert.ToInt32(oHandlingInfo.qty);
}
}
}
}
oReturnsDetail.received_qty = oReturnsDetail.destroy + oReturnsDetail.to_shop + oReturnsDetail.in_stock;
}
dgReturnsDetail.DataSource = lstReturnsDetail.OrderByDescending(g => g.id).ToList();
Session[DCReturnsConstants.Returns_Detail_Entity] = lstReturnsDetail;
dgReturnsDetail.DataBind();
this is su-do code! but you should get the jist.
//modify this to return all of them into mem, and then filter on this...
//if it can not be done here then do below..
var lstReturnsDetail = dcReturnsService.GetReturnDetailsInfo(header_id);
//then create a list here which fetches all,
List<[type]> somelist
List<int> listId = lstReturnsDetail.select(x=>x.id).tolist();
using (var db = new DCReturns_Entities())
{
somelist = db.HandlingInfoes.Where(f => listId.Contains( f.detail_id)).ToList();
}
foreach (ReturnsDetail oReturnsDetail in lstReturnsDetail)
{
//performance issue is here
//using (DCReturns_Entities entities = new DCReturns_Entities())
//{
// lstHandlingInfo = entities.HandlingInfoes.Where(f => f.detail_id == oReturnsDetail.id).ToList();
//}
//insead fetach all before, into mem and filter from that list.
var lstHandlingInfo = somelist.Where(f => f.detail_id == oReturnsDetail.id).ToList();
//code ommited for reaablity
}
//code ommited for reaablity

How to add a new function to Ncalc

I'm using Ncalc in my new project and it already has almost everything I need .
I said almost everything, because now I need to expand some functions and also add new ones such as : nth root,random, etc
Do you know if anyone has already implemented those functions? Or could you give me any tips or guides to extend the function list of Ncalc???
Thanks in advance.
If I understand correctly:
As much as I was using it is by creating a static function
private static void NCalcExtensionFunctions(string name, FunctionArgs functionArgs)
{
if (name == "yourfunctionname")
{
var param1 = functionArgs.Parameters[0].Evaluate();
var param2 = functionArgs.Parameters[1].Evaluate();
//... as many params as you require
functionArgs.Result = (int)param1 * (int)param2; //do your own function logic here
}
if (name == "random")
{
if(functionArgs.Parameters.Count() == 0)
{
functionArgs.Result = new Random().Next();
}
else if(functionArgs.Parameters.Count() == 1)
{
functionArgs.Result = new Random().Next((int)functionArgs.Parameters[0].Evaluate());
}
else
{
functionArgs.Result = new Random().Next((int)functionArgs.Parameters[0].Evaluate(), (int)functionArgs.Parameters[1].Evaluate());
}
}
}
And then you use it as follows
var expr = new Expression("yourfunctionname(3, 2)");
expr.EvaluateFunction += NCalcExtensionFunctions;
var result = expr.Evaluate();
var randExpr = new Expression("random(100)");
randExpr.EvaluateFunction += NCalcExtensionFunctions;
var resultRand = randExpr.Evaluate();
I hope I didn't mistype any of the code. A list of NCalc built-in functions can be found here: http://ncalc.codeplex.com/wikipage?title=functions&referringTitle=Home

First method of Linq giving error

In my webmethod of my WCF rest service i am trying to find record using Linq's First method like below
[WebInvoke(UriTemplate = "UpdateProductObject", Method = "PUT")]
public Result UpdateProductObject(ProductObjectToSave prodSave)
{
IUnitOfWork unitOfWork = new UnitOfWork((IObjectContext)_objectSetFactory);
var versions = prodSave.VersionDetails;
foreach (var versionDetail in versions)
{
var detail = versionDetail;
var dbVersionentity = _productVersionEntityRepository.First(x => x.Id == detail.Id);
if (detail.Id < 0)
{
dbVersionentity.Id = GetNextTableId("vProductVersion");
}
dbVersionentity.Name = detail.Name;
dbVersionentity.Code = detail.Name;
if (detail.Id > 0){
_productVersionEntityRepository.Update(dbVersionentity);
}
else
{
_productVersionEntityRepository.Insert(dbVersionentity);
}
}
try
{
unitOfWork.Commit();
}
catch (Exception e)
{
return new Result() { Error = e.Message };
}
return new Result() { Error = "Record updated successfully" };
}
The "_productVersionEntityRepository" is defined as below in my service.
private readonly Repository<ProductVersionEntity> _productVersionEntityRepository;
When there are no records it throws exception "Sequence contains no elements" . I have done some finding that we can use FirstOrDefault method. But somehow i am not getting that option to use FirstOrDefault. I am really new to this so may be i have missed some links where solution could have been described. Please help me or suggest me other way to do some error handling if First method fails
That's the way that First() works, it will throw an exception if the element can't be found. You can use FirstorDefault() instead and check if the element is null.
Edit: I realised that you're using a custom repository. If you have access to the source code, I advise you to add a new method called .FirstOrDefault() that will take as parameter a predicate and returns null if no entities are found.
Edit 2: Add this method to your repository:
T FirstOrDefault(Expression<Func<T, bool>> where, params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = AsQueryable();
query = PerformInclusions(includeProperties, query);
return query.FirstOrDefault(where);
}
Then you can do something like this in your code:
foreach (var versionDetail in versions)
{
bool isNew = false;
var detail = versionDetail;
var dbVersionentity = _productVersionEntityRepository.FirstOrDefault(x => x.Id == detail.Id);
// not found in database
if(dbVersionentity == null)
{
isNew = true;
// create entity here
dbVersionentity = new .....;
// you don't need to do this if id is auto-generated,
// i.e. Identity column in SQL Server
dbVersionentity.Id = GetNextTableId("vProductVersion");
}
dbVersionentity.Name = detail.Name;
dbVersionentity.Code = detail.Name;
if (isNew)
{
_productVersionEntityRepository.Insert(dbVersionentity);
}
else
{
_productVersionEntityRepository.Update(dbVersionentity);
}
}
try
var dbVersionentity = _productVersionEntityRepository.Where(x => x.Id == detail.Id).FirstOrDefault();

Categories

Resources