DbSet.Remove() seems like to remove sometimes - c#

Hello I have this project on Entity Framework for an exam, I have 157 test to pass and I pass 155, the last 2 are very similar to others but I dont understand why fails, I put some code so I can explain better:
public void GetUsers_OnDeletedObject_Throws() {
Site.Delete();
Assert.That(() => Site.GetUsers(), Throws.TypeOf<InvalidOperationException>()); }
I defined the Delete() method to recorsively call Delete to resources in the site(like users), then remove the site from the context.
From now on any method in the site must throw InvalidOperationException because the site doesn't exist anymore, but in some way Site.GetUsers() find a site and dont throw.
The real mistery is if I try to insert other methods (written in same way) between the delete and the assert the extra method throw InvalidOperationException!
Site.Delete() code:
using (var ctx = new SiteContext(connectionString))
{
var site = ctx.Sites.Find(Name);
foreach (var a in GetAuctions()) ctx.Auctions.Remove(a);
foreach (var s in GetSessions()) ctx.Sessions.Remove(s);
foreach (var u in GetUsers()) ctx.Users.Remove(u);
ctx.Sites.Remove(site);
ctx.SaveChanges();
}
Part of GetUsers where should throw
public IEnumerable<IUser>GetUsers()
{
using (var ctx = new SiteContext(connectionString))
{
var site = ctx.Sites.SingleOrDefault(s => s.Name == Name);
AlreadyDeleted(site);
AlreadyDeleted() code:
public static void AlreadyDeleted(object o)
{
if (null == o) throw new InvalidOperationException();
}

Related

Removing Claims from ClaimPrincipal in C#

I am kind of scratching my head to resolve this issue where I have to remove all the Claims in one go. When I use the below code, I get this error Collection was modified; enumeration operation may not execute
Since, I am changing/modifying the value from the enumerator that I am currently looping through, therefore, I am getting this error. Any idea how can I resolve this issue. I have used the below code:
private static readonly string[] claimTypes=
{
ClaimTypes.Role,
ClaimTypes.UserSpecific.IdleSessionTimeout,
ClaimTypes.CustomerSpecific.ApplicationId,
ClaimTypes.CustomerSpecific.CustomerId,
ClaimTypes.CustomerSpecific.CustomerName,
ClaimTypes.CustomerSpecific.CurrencyCode,
ClaimTypes.CustomerSpecific.Locale,
ClaimTypes.CustomerSpecific.TimeZone,
ClaimTypes.CustomerSpecific.ReportingUnitId
};
public static void RemoveClaimsFor(this ClaimsPrincipal principal, params string[] claimTypes)
{
if (principal == null) throw new ArgumentNullException(nameof(principal));
foreach (var identity in principal.Identities)
{
foreach (var claim in identity.FindAll(claim => claimTypes.Any(type => type == claim.Type)))
{
identity.TryRemoveClaim(claim);
}
}
}
Since this was giving error so I thought of using the below code. but this also does not work.
public static void RemoveClaimsFor(this ClaimsPrincipal principal, params string[] claimTypes)
{
if (principal == null) throw new ArgumentNullException(nameof(principal));
var claimNamedList = principal.Identities.Select(x=>x.Claims.Select(y=>y.Type).ToList());
foreach (var identity in principal.Identities)
{
var claimNameList = identity.FindAll(claim => claimTypes.Any(type => type == claim.Type));
foreach (var name in claimNameList)
{
var aa = principal.Identities.Select(x => x.Claims.Where(b => b.Type == name.Type));
identity.TryRemoveClaim(name);
}
}
}
In order to solve this, you need to create a new collection that you enumerate:
public static void RemoveClaimsFor(this ClaimsPrincipal principal, params string[] claimTypes)
{
if (principal == null) throw new ArgumentNullException(nameof(principal));
foreach (var identity in principal.Identities)
{
var claimsToRemove = identity
.FindAll(claim => claimTypes.Any(type => type == claim.Type))
.ToArray();
foreach (var claim in claimsToRemove)
{
identity.TryRemoveClaim(claim);
}
}
}
By using ToArray (or ToListor another To* method), the results of the enumeration are stored in a new collection that you can enumerate over. When removing items, this does not affect the newly created collection so the error will be gone.

C# - how to delete row in realm - android xamarin

i tried this method that I created but it prompts me an error:
Realms.RealmInvalidObjectException:This object is detached. Was it deleted from the realm?'
public void deleteFromDatabase(List<CashDenomination> denom_list)
{
using (var transaction = Realm.GetInstance(config).BeginWrite())
{
Realm.GetInstance(config).Remove(denom_list[0]);
transaction.Commit();
}
}
what is the proper coding for deleting records from database in realm in C# type of coding?
You are doing it the right way. The error message you are getting indicates that the object was removed already. Are you sure it still exists in the realm?
UPDATE:
I decided to update this answer because my comment on the other answer was a bit hard to read.
Your original code should work fine. However, if you want deleteFromDatabase to accept lists with CashDenomination instances that either have been removed already or perhaps were never added to the realm, you would need to add a check. Furthermore, note that you should hold on to your Realm instance and use it in the transaction you created. In most cases, you want to keep it around even longer, though there is little overhead to obtaining it via GetInstance.
public void deleteFromDatabase(List<CashDenomination> denom_list)
{
if (!denom_list[0].IsValid) // If this object is not in the realm, do nothing.
return;
var realm = Realm.GetInstance(config);
using (var transaction = realm.BeginWrite())
{
realm.Remove(denom_list[0]);
transaction.Commit();
}
}
Now, if you want to use identifiers, you could look it up like you do, but still just use Remove:
public void deleteFromDatabase(int denom_id)
{
var realm = Realm.GetInstance(config);
var denom = realm.All<CashDenomination>().FirstOrDefault(c => c.denom_id == denom_id);
if (denom == null) // If no entry with this id exists, do nothing.
return;
using (var transaction = realm.BeginWrite())
{
realm.Remove(denom);
transaction.Commit();
}
}
Finally, if your CashDenomination has denom_id marked as PrimaryKey, you could look it up like this:
public void deleteFromDatabase(int denom_id)
{
var realm = Realm.GetInstance(config);
var denom = realm.ObjectForPrimaryKey<CashDenomination>(denom_id);
if (denom == null) // If no entry with this id exists, do nothing.
return;
using (var transaction = realm.BeginWrite())
{
realm.Remove(denom);
transaction.Commit();
}
}
public void deleteFromDatabase(Realm realm, long cashDenominatorId)
{
realm.Write(() =>
{
var cashDenominator = realm.All<Person>().Where(c => c.Id == cashDenominatorId);
Realm.RemoveRange<CashDenomination>(((RealmResults<CashDenomination>)cashDenominator));
});
}
Which you would call as
Realm realm = Realm.GetInstance(config);
var denom_list = ...
// ...
deleteFromDatabase(realm, denom_list[0].id);
I already made it having this code :) thanks to #EpicPandaForce 's answer.
public void deleteFromDatabase(int denom_ID, int form_ID)
{
//Realm realm;
//and
//RealmConfiguration config = new RealmConfiguration(dbPath, true);
//was initialized at the top of my class
realm = Realm.GetInstance(config);
realm.Write(() =>
{
var cashflow_denom = realm.All<CashDenomination>().Where(c => c.denom_id == denom_ID);
var cashflow_form = realm.All<CashForm>().Where(c => c.form_id == form_ID);
realm.RemoveRange(((RealmResults<CashDenomination>)cashflow_denom));
realm.RemoveRange(((RealmResults<CashForm>)cashflow_form));
});
}
it is now deleting my data without exception :)

ASP.Net Calling method from another namespace

I have two projects, the first one with a ClassLibraryServer namespace and Output method as following :
namespace ClassLibraryServer
{
public class Output
{
public static void Card(tblCard card, int myProperty)
{
if (kort.fltNr.Length != 6)
return;
using (myDataContext db = new myDataContext(ClassLibrary.Settings.Instance.SqlS))
{
tblReader[] readers = (from row in db.tblReader
where !row.fltOffline
select row).ToArray();
bool blocked = (db.tblCardBlocked.Where(b => b.fltProperty == myProperty && b.fltCard == card.id).FirstOrDefault() != null);
foreach (tblReader reader in readers)
{
Card(card, reader, blocked);
}
}
}
}
}
The Card method in foreach loop calls another method (Overloading the first card method) which has three parameters and inserts data to a sql table, I won't share it here as it takes too much space.
Now I want to call above method in another project with namespace ExtControlModule:
namespace ExtControlModule
{
public class TimeModule
{
using (ModuleDataContext dbsys = new ModuleDataContext(ClassLibrary.Settings.Instance.SqlS)) {
var loungee = (from tblLounge in dbsys.tblLounges
select tblLounge).ToList();
var lasaresFas = 0;
foreach (var LoungeRow in loungee)
{
lasaresFas= Convert.ToInt32(dbsys.tblLasares.FirstOrDefault(f => f.id == LoungeRow.fltCardreader).fltproperty);
tblCard cardLoading = dbsys.tblCard.FirstOrDefault(t => t.id == res.fltCardnumber);
Output.Card(cardLoading, lasaresFas);
}
}
}
Now when I want to assign parameters to Output.Card in ExtControlModule I get the following error in cardLoading parameter in Output.Card:
Argument !: cannot convert from 'ExtControlModule.tblCard' to ClassLibrary.db.tblCard'
ClassLibrary is another project in the same Solution which contains a public class Settings with the SqlS property which facilitate connection to SQL database.
Struggling with this for many days as I am new to both ASP.NET and Sql, hope my question is clear enough.
call method
ClassLibraryServer.Output.Card(cardLoading, lasaresFas);

How to access and modify a node with code fix provider from another node

I have a situation where I need to modify a situation where a user writes this kind of code :
bool SomeMethod(object obj)
{
if(obj == null)
return false;
return true;
}
To the following code :
bool SomeMethod(object obj)
{
return obj == null;
}
Currently, I have built an analyzer that works. I'll put the code below. Basically, the analyzer looks for if statements and verifies if the only statement of the if is a return statement.Not only that, it verifies that also, the next statement inside the method's declaration is a return statement.
The code fix provider looks for the ifStatement's condition and creates a new return statement using that condition. What I'm trying to do after replacing the if statement by the return statement, is to remove the second return statement. At this, I'm failing without knowing how.
At first, when the node's been replaced, I create a new root, because they can't be modify like a string, it's about the same thing. I try to delete the node, but this instruction is being ignored for some reason. And I've debugged it, when I access the next node(ReturnStatement), it's not null.
I guess my question is basically, how can I build a code fix provider which can modify a node without being "linked" on it.
Here's the code for the analyzer
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class RewriteIfReturnToReturnAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor descriptor = new DiagnosticDescriptor(
CSharpDiagnosticIDs.RewriteIfReturnToReturnAnalyzerID,
GettextCatalog.GetString("Convert 'if...return' to 'return'"),
GettextCatalog.GetString("Convert to 'return' statement"),
DiagnosticAnalyzerCategories.Opportunities,
DiagnosticSeverity.Info,
isEnabledByDefault: true,
helpLinkUri: HelpLink.CreateFor(CSharpDiagnosticIDs.RewriteIfReturnToReturnAnalyzerID)
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(
(nodeContext) =>
{
Diagnostic diagnostic;
if (TryGetDiagnostic(nodeContext, out diagnostic))
{
nodeContext.ReportDiagnostic(diagnostic);
}
}, SyntaxKind.IfStatement);
}
private static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic)
{
diagnostic = default(Diagnostic);
if (nodeContext.IsFromGeneratedCode())
return false;
var node = nodeContext.Node as IfStatementSyntax;
var methodBody = node?.Parent as BlockSyntax;
var ifStatementIndex = methodBody?.Statements.IndexOf(node);
if (node?.Statement is ReturnStatementSyntax &&
methodBody?.Statements.ElementAt(ifStatementIndex.Value + 1) is ReturnStatementSyntax)
{
diagnostic = Diagnostic.Create(descriptor, node.GetLocation());
return true;
}
return false;
}
}
}
Here's the code for the Code fix provider
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[ExportCodeFixProvider(LanguageNames.CSharp), System.Composition.Shared]
public class RewriteIfReturnToReturnCodeFixProvider : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
{
get
{
return ImmutableArray.Create(CSharpDiagnosticIDs.RewriteIfReturnToReturnAnalyzerID);
}
}
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var span = context.Span;
var diagnostics = context.Diagnostics;
var root = await document.GetSyntaxRootAsync(cancellationToken);
var diagnostic = diagnostics.First();
var node = root.FindNode(context.Span);
if (node == null)
return;
context.RegisterCodeFix(
CodeActionFactory.Create(node.Span, diagnostic.Severity, "Convert to 'return' statement", token =>
{
var statementCondition = (node as IfStatementSyntax)?.Condition;
var newReturn = SyntaxFactory.ReturnStatement(SyntaxFactory.Token(SyntaxKind.ReturnKeyword),
statementCondition, SyntaxFactory.Token(SyntaxKind.SemicolonToken));
var newRoot = root.ReplaceNode(node as IfStatementSyntax, newReturn
.WithLeadingTrivia(node.GetLeadingTrivia())
.WithAdditionalAnnotations(Formatter.Annotation));
var block = node.Parent as BlockSyntax;
if (block == null)
return null;
//This code (starting from here) does not do what I'd like to do ...
var returnStatementAfterIfStatementIndex = block.Statements.IndexOf(node as IfStatementSyntax) + 1;
var returnStatementToBeEliminated = block.Statements.ElementAt(returnStatementAfterIfStatementIndex) as ReturnStatementSyntax;
var secondNewRoot = newRoot.RemoveNode(returnStatementToBeEliminated, SyntaxRemoveOptions.KeepNoTrivia);
return Task.FromResult(document.WithSyntaxRoot(secondNewRoot));
}), diagnostic);
}
}
}
And finally, this is my NUnit test :
[Test]
public void When_Retrurn_Statement_Corrected()
{
var input = #"
class TestClass
{
bool TestMethod (object obj)
{
$if (obj != null)
return true;$
return false;
}
}";
var output = #"
class TestClass
{
bool TestMethod (object obj)
{
return obj!= null;
}
}";
Analyze<RewriteIfReturnToReturnAnalyzer>(input, output);
}
I believe the problem is probably this line:
var block = node.Parent as BlockSyntax;
You're using the node from the original tree, with a .Parent also from the original tree (not the one with the updated newReturn).
Then, it eventually calculates returnStatementToBeEliminated using this old tree that's no longer up-to-date, so when you call var secondNewRoot = newRoot.RemoveNode(returnStatementToBeEliminated, SyntaxRemoveOptions.KeepNoTrivia);, nothing happens because newRoot does not contain returnStatementToBeEliminated.
So, you basically want to use the equivalent of node.Parent, but the version that lives under newRoot. The low-level tool we use for this is called a SyntaxAnnotation, and these have the property that they track forward between tree edits. You can add a specific annotation to the node.Parent before making any edits, then make your edits, and then ask the newRoot to find the node with your annotation.
You can track nodes manually like this, or you can use the SyntaxEditor class, which abstracts the Annotations part away into simpler methods like TrackNode (there's a few other nice features in SyntaxEditor that you may want to check out).
For this issue, I was refer to the following post :
How do I create a new root by adding and removing nodes retrieved from the old root?
This post showed this class called DocumentEditor, which lets a user modify a document like he wants even though it's suppose to be immutable. The previous issue was that after deleting a node, if I was referring something that had a connection to that node, the relation would have disappear and I would be able to stuff.
Basically, the documentation comment says that this class is "an editor for making changes to a document's syntax tree."
After you're done modifying that document, you need to create a new document and return it as a Task in the code fix provider.
To solve this issue I had with my code fix provider, I used the following code :
context.RegisterCodeFix(CodeAction.Create("Convert to 'return' statement", async token =>
{
var editor = await DocumentEditor.CreateAsync(document, cancellationToken);
var statementCondition = (node as IfStatementSyntax)?.Condition;
var newReturn = SyntaxFactory.ReturnStatement(SyntaxFactory.Token(SyntaxKind.ReturnKeyword),
statementCondition, SyntaxFactory.Token(SyntaxKind.SemicolonToken));
editor.ReplaceNode(node as IfStatementSyntax, newReturn
.WithLeadingTrivia(node.GetLeadingTrivia())
.WithAdditionalAnnotations(Formatter.Annotation));
var block = node.Parent as BlockSyntax;
if (block == null)
return null;
var returnStatementAfterIfStatementIndex = block.Statements.IndexOf(node as IfStatementSyntax) + 1;
var returnStatementToBeEliminated = block.Statements.ElementAt(returnStatementAfterIfStatementIndex) as ReturnStatementSyntax;
editor.RemoveNode(returnStatementToBeEliminated);
var newDocument = editor.GetChangedDocument();
return newDocument;
}, string.Empty), diagnostic);
It was really simple to solve my issue thanks to that class.

Unable to loop through and delete child records

I have the following action method:-
try
{
repository.DeleteServer(id, ADusername);
repository.Save();
return Json(new { IsSuccess = "True", id = id, description = tag }, JsonRequestBehavior.AllowGet);
}
which will call the following repository method to delete an object:-
public void DeleteServer(int id,string username)
{
var server = tms.TMSServers.SingleOrDefault(a=>a.TMSServerID == id);
var auditinfo = IntiateTechnologyAudit(tms.AuditActions.SingleOrDefault(a => a.Name.ToUpper() == "DELETE").ID,
server.Technology.TechnologyType.AssetTypeID,
username, server.TMSServerID);
var technology = tms.Technologies.Include(a=>a.TMSSwitchPorts).SingleOrDefault(a => a.TechnologyID == id);
technology.IsDeleted = true;
tms.Entry(technology).State = EntityState.Modified;
tms.TMSServers.Remove(server);
foreach (var switchport in technology.TMSSwitchPorts)
{
tms.TMSSwitchPorts.Remove(switchport);
}
InsertOrUpdateTechnologyAudit(auditinfo);
}
the problem i am facing is insdie the foreach where the deletion will not be performed and no exception will be raised. when i debug my code the action method will call the deleteserver methods, then when the code reach the foreach it will not iterate over the technology.TMSSwtichPort instead the code will break without errors and the .save inside my action method will not be reached ?can any one advice what might be the problem ?
Thanks
I would imagine it's because you are using a foreach over a collection that you are indirectly modifying by deleting members.
Running your foreach over a separate collection might help, because then your enumeration isn't invalidated by the delete:
var toDelete = technology.TMSSwitchPorts.ToList();
foreach (var switchport in toDelete)
{
tms.TMSSwitchPorts.Remove(switchport);
}

Categories