I am new in creating Addins for Enterprise Architect and I have this problem:
I have a diagram with elements which have TaggedValues. I want to get notified when the value of a TaggedValue changes and see the new value.
I saw that there is this event EA_OnElementTagEdit available but I can't seem to get it triggered. I also saw that the tagged value has to be of type AddinBroadcast but I can't seem to make it work. What am I missing?
I will put below a sample of my code:
//creating tagged value
EA.TaggedValue ob3 = (EA.TaggedValue)NewElement.TaggedValues.AddNew("Responsible", "val");
ob3.Value = EEPROMBlocks.ElementAt(index).Responsible;
ob3.SetAttribute("Type", "AddinBroadcast");
ob3.Update();
//event method
public override void EA_OnElementTagEdit(EA.Repository Repository, long ObjectID, ref string TagName, ref string TagValue, ref string TagNotes)
You are not missing anything. This is simply not possible. The only way around is the OnContext... where you temporarily store the status of one element and look if a tag has changed when the context changes. I would not recommend that since it involved a lot of superfluous DB accesses.
Send a feature request (if you are an optimistic guy). Alternatively you should think of ways to get around this somehow else.
I am having troubles inserting entities in linq after deleting them (without submitting the changes).
List<AlergiesPerPersonBE> AlergiesPerPerson = AlergiesPerPersonToInsert;
RepositoryFactory.GetAlergiesPerPersonRepository().DeleteWhere(x => x.PersonId == id);
RepositoryFactory.GetAlergiesPerPersonRepository().Insert(AlergiesPerPerson);
DataContextFactory.SubmitChanges();
Both (delete and insert) donĀ“t submit any changes. They just InsertAllOnSubmit and DeleteAllOnSumbit.
The code works fine the first time. All the details are inserted properly. The second time that I run the same code, all rows of the db are deleted. The third time, all works fine. It works, then it doesn't, and so on.
Try
...DeleteWhere(x => x.PersonId == id);
DataContextFactory.SubmitChanges();
...Insert(AlergiesPerPerson);
DataContextFactory.SubmitChanges();
There's no reason that you have to submit changes only once per unit of work. Note that this will still work with any transactions that you have.
I think you will have to recreate the details again.
The context is currently tracking this item as being 'deleted' even if save changes hasn't yet been called.
There is dirty work around. Since you want to get rid of DataContext observer you will need to:
serialize object or graph to memory
stream.
Then deserialize it back as new instance
change ID to 0
Attach new object to DataContext and submit
changes.
Delete previous
You can move this to CloneHelper static class so you can use it for any type
I'm using Fluent NHibernate (the NH3 build - #694) and LINQ to connect to an Oracle 11 database. However, I don't seem to be able to get any data from the database. The connection seems to be working, as, if I change my login info, it throws an error.
I'm using the following code:
// Setup.
OracleClientConfiguration oracleClientConfiguration =
OracleClientConfiguration.Oracle10
.ShowSql()
.ConnectionString(connectionString);
_sessionFactory =
Fluently.Configure()
.Database(oracleClientConfiguration)
.Mappings(m => m.FluentMappings
.AddFromAssemblyOf<Feed>())
.BuildSessionFactory();
// Query.
using (ISession session = _sessionFactory.OpenSession())
{
IEnumerable<Category> categories = session.Query<Category>().ToList(); // Returns empty list.
// And so on...
}
I have a map for the Category table, but, no matter what I put in there, I still get an empty list. Also, even though I use ShowSql(), I'm not seeing any NHibernate output in the VS (2010) window.
I'm using TestDriven.NET (3.x) to run the code. No errors are thrown and the Assert.NotEmpty (xUnit) on the returned collection fails (obviously).
I'm stuck, as the code is running and just returning nothing and I can't get any diagnostic info. I even tried getting NHibernate to write to log4net (TraceAppender), but, again, nothing.
I'd appreciate any pointers - even if it's a way of getting the thing to tell me what it's trying to do.
Turns out that one of the classes used in the mapping was marked "internal".
Can you try replacing the lower block of your code with this?
using (ISession session = _sessionFactory.OpenSession())
{
IEnumerable<Category> categories = session.CreateCriteria(typeof(Category)).List<Category>();
}
At first glance I suspect the issue is your use of ToList() instead of List<T>(), but please let me know if this suggestion gets you past the immediate issue.
Check the Fluent NHibernate xml files. I face the same problem and after all I realize that my xml files were out-of-date.
I get System.NotSupportedException: An attempt has been made to Attach or Add an entity that is not new perhaps having been loaded from another DataContext when I want to update an object's with child entities.
The scenario is like this:
I have a SubscriberProvider that allows me to create subscribers.
var provider = new SubscriberProvider(); // Creates a new repository with own datacontext
var newSubscriber = new Subscriber
{
EmailAddress = emailAddress,
};
newSubscriber.Interests.Add(new Interest{
Id=1,
Name="cars"
});
provider.Subscribe(newSubscriber);
On a normal subscribe page, this works fine.
Now I have a linq2sql Member class(retrievable by a MemberRepository) and I want to extend it to have a helper subscribe method like so:
var repository = new MembershipRepository(); // Holds its own datacontext
var member = repository.Get("member1");
member.Subscribe(); // transfer member's info and interests to subscriber's table
The exception occurs when SubscriberProvider tries to add interests of the member.
Commenting out
newSubscriber.Interests.Add(new Interest{
Id=1,
Name="cars"
});
will make member.Subscribe() work.
member.Subscribe() is simply:
public void Subscribe(bool emailIsVerified, bool receiveEmails, bool sendDoubleOptIn)
{
var provider = new MailingListProvider();
provider.Subscribe(EmailAddress, emailIsVerified, receiveEmails, CountryId, sendDoubleOptIn, ConvertInterests(MemberInterests.ToList()));
}
So what's causing the child entities(Interests) to lose their datacontext when I do member.Subscribe() and how do I go about fixing this?
It seems there's some code missing here, but I'll take a stab anyway because I think I have an idea what's going on.
If you have a different DataContext created for your MembershipRepository and your SubscriberRepository you're going to have issues related to entities "having been loaded from another DataContext." (as the Exception you posted points out). You can't just take an object out of one DataContext and save it into another.
It seems that you might have an architectural issue here. Should these 2 repositories actually be separate? If so, should they have completely different DataContexts? I would probably recommend using Dependency Injection to inject your DataContexts into your Repositories. Then you can decide how to cache your DataContexts.
That line of code you commented out is being flagged by the DataContext as a new record, even though it's likely that the record already exists, due to the error message.
Change the line to:
newSubscriber.Interests.Add(DataContext.Interests.Where(a => a.Id == 1).Single());
Now, the DataContext will know that record is one that already exists, and won't try to add it as an Insert to the ChangeSet.
Found the solution to this myself. Turns out it was the ConvertInterests() method causing it. The converted interest object had an invalid declaration which compiled ok.
Thinking the code was simple enough, I didn't create a test for it. I should have known better!
I am having a really hard time attempting to debug LINQ to SQL and submitting changes.
I have been using http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx, which works great for debugging simple queries.
I'm working in the DataContext Class for my project with the following snippet from my application:
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.SubmitChanges();
I will catch some very odd exceptions when I run this.SubmitChanges;
Index was outside the bounds of the array.
The stack trace goes places I cannot step into:
at System.Data.Linq.IdentityManager.StandardIdentityManager.MultiKeyManager`3.TryCreateKeyFromValues(Object[] values, MultiKey`2& k)
at System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache`2.Find(Object[] keyValues)
at System.Data.Linq.IdentityManager.StandardIdentityManager.Find(MetaType type, Object[] keyValues)
at System.Data.Linq.CommonDataServices.GetCachedObject(MetaType type, Object[] keyValues)
at System.Data.Linq.ChangeProcessor.GetOtherItem(MetaAssociation assoc, Object instance)
at System.Data.Linq.ChangeProcessor.BuildEdgeMaps()
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges()
at JobTrakDataContext.CreateNewJob(NewJob job, String userName) in D:\JobTrakDataContext.cs:line 1119
Does anyone have any tools or techniques they use? Am I missing something simple?
EDIT:
I've setup .net debugging using Slace's suggestion, however the .net 3.5 code is not yet available: http://referencesource.microsoft.com/netframework.aspx
EDIT2:
I've changed to InsertOnSubmit as per sirrocco's suggestion, still getting the same error.
EDIT3:
I've implemented Sam's suggestions trying to log the SQL generated and to catch the ChangeExceptoinException. These suggestions do not shed any more light, I'm never actually getting to generate SQL when my exception is being thrown.
EDIT4:
I found an answer that works for me below. Its just a theory but it has fixed my current issue.
I always found useful to know exactly what changes are being sent to the DataContext in the SubmitChanges() method.
I use the DataContext.GetChangeSet() method, it returns a ChangeSet object instance that holds 3 read-only IList's of objects which have either been added, modified, or removed.
You can place a breakpoint just before the SubmitChanges method call, and add a Watch (or Quick Watch) containing:
ctx.GetChangeSet();
Where ctx is the current instance of your DataContext, and then you'll be able to track all the changes that will be effective on the SubmitChanges call.
First, thanks everyone for the help, I finally found it.
The solution was to drop the .dbml file from the project, add a blank .dbml file and repopulate it with the tables needed for my project from the 'Server Explorer'.
I noticed a couple of things while I was doing this:
There are a few tables in the system named with two words and a space in between the words, i.e. 'Job Master'. When I was pulling that table back into the .dbml file it would create a table called 'Job_Master', it would replace the space with an underscore.
In the orginal .dbml file one of my developers had gone through the .dbml file and removed all of the underscores, thus 'Job_Master' would become 'JobMaster' in the .dbml file. In code we could then refer to the table in a more, for us, standard naming convention.
My theory is that somewhere, the translation from 'JobMaster' to 'Job Master' while was lost while doing the projection, and I kept coming up with the array out of bounds error.
It is only a theory. If someone can better explain it I would love to have a concrete answer here.
My first debugging action would be to look at the generated SQL:
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.Log = Console.Out; // prints the SQL to the debug console
this.SubmitChanges();
The second would be to capture the ChangeConflictException and have a look at the details of failure.
catch (ChangeConflictException e)
{
Console.WriteLine("Optimistic concurrency error.");
Console.WriteLine(e.Message);
Console.ReadLine();
foreach (ObjectChangeConflict occ in db.ChangeConflicts)
{
MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType());
Customer entityInConflict = (Customer)occ.Object;
Console.WriteLine("Table name: {0}", metatable.TableName);
Console.Write("Customer ID: ");
Console.WriteLine(entityInConflict.CustomerID);
foreach (MemberChangeConflict mcc in occ.MemberConflicts)
{
object currVal = mcc.CurrentValue;
object origVal = mcc.OriginalValue;
object databaseVal = mcc.DatabaseValue;
MemberInfo mi = mcc.Member;
Console.WriteLine("Member: {0}", mi.Name);
Console.WriteLine("current value: {0}", currVal);
Console.WriteLine("original value: {0}", origVal);
Console.WriteLine("database value: {0}", databaseVal);
}
}
}
You can create a partial class for your DataContext and use the Created or what have you partial method to setup the log to the console.out wrapped in an #if DEBUG.. this will help you to see the queries executed while debugging any instance of the datacontext you are using.
I have found this useful while debugging LINQ to SQL exceptions..
partial void OnCreated()
{
#if DEBUG
this.Log = Console.Out;
#endif
}
The error you are referring to above is usually caused by associations pointing in the wrong direction. This happens very easily when manually adding associations to the designer since the association arrows in the L2S designer point backwards when compared to data modelling tools.
It would be nice if they threw a more descriptive exception, and maybe they will in a future version. (Damien / Matt...?)
This is what I did
...
var builder = new StringBuilder();
try
{
context.Log = new StringWriter(builder);
context.MY_TABLE.InsertAllOnSubmit(someData);
context.SubmitChanges();
}
finally
{
Log.InfoFormat("Some meaningful message here... ={0}", builder);
}
A simple solution could be to run a trace on your database and inspect the queries run against it - filtered ofcourse to sort out other applications etc. accessing the database.
That ofcourse only helps once you get past the exceptions...
VS 2008 has the ability to debug though the .NET framework (http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx)
This is probably your best bet, you can see what's happening and what all the properties are at the exact point in time
Why do you do UpdateJobMaster on a new instance ? Shouldn't it be InsertOnSubmit ?
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.InsertOnSubmit(newJobToCreate);
this.SubmitChanges();
This almost certainly won't be everyone's root cause, but I encountered this exact same exception in my project - and found that the root cause was that an exception was being thrown during construction of an entity class. Oddly, the true exception is "lost" and instead manifests as an ArgumentOutOfRange exception originating at the iterator of the Linq statement that retrieves the object/s.
If you are receiving this error and you have introduced OnCreated or OnLoaded methods on your POCOs, try stepping through those methods.
Hrm.
Taking a WAG (Wild Ass Guess), it looks to me like LINQ - SQL is trying to find an object with an id that doesn't exist, based somehow on the creation of the JobMaster class. Are there foreign keys related to that table such that LINQ to SQL would attempt to fetch an instance of a class, which may not exist? You seem to be setting the ProjectID of the new object to a string - do you really have an id that's a string? If you're trying to set it to a new project, you'll need to create a new project and get its id.
Lastly, what does UpdateJobMaster do? Could it be doing something such that the above would apply?
We have actually stopped using the Linq to SQL designer for our large projects and this problem is one of the main reasons. We also change a lot of the default values for names, data types and relationships and every once in a while the designer would lose those changes. I never did find an exact reason, and I can't reliably reproduce it.
That, along with the other limitations caused us to drop the designer and design the classes by hand. After we got used to the patterns, it is actually easier than using the designer.
I posted a similar question earlier today here: Strange LINQ Exception (Index out of bounds).
It's a different use case - where this bug happens during a SubmitChanges(), mine happens during a simple query, but it is also an Index out of range error.
Cross posting in this question in case the combination of data in the questions helps a good Samaritan answer either :)
Check that all the "primary key" columns in your dbml actually relate to the primary keys on the database tables. I just had a situation where the designer decided to put an extra PK column in the dbml, which meant LINQ to SQL couldn't find both sides of a foreign key when saving.
I recently encountered the same issue: what I did was
Proce proces = unit.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes
where pt.Name == "Fix-O"
select pt).Single().ProcesTypeId &&
u.UnitId == UnitId);
Instead of:
Proce proces = context.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes
where pt.Name == "Fix-O"
select pt).Single().ProcesTypeId &&
u.UnitId == UnitId);
Where context was obviously the DataContext object and "unit" an instance of Unit object, a Data Class from a dbml file.
Next, I used the "proce" object to set a property in an instance of another Data Class object. Probably the LINQ engine could not check whether the property I was setting from the "proce" object, was allowed in the INSERT command that was going to have to be created by LINQ to add the other Data Class object to the database.
I had the same non speaking error.
I had a foreign key relation to a column of a table that was not the primary key of the table, but a unique column.
When I changed the unique column to be the primary key of the table the problem went away.
Hope this helps anyone!
Posted my experiences with this exception in an answer to SO# 237415
I ended up on this question when trying to debug my LINQ ChangeConflictException. In the end I realized the problem was that I manually added a property to a table in my DBML file, but I forgot to set the properties like Nullable (should have been true in my case) and Server Data Type
Hope this helps someone.
This is a long time ago, but I had the same problem and the error was because of a trigger with a select statement. Something like
CREATE TRIGGER NAME ON TABLE1 AFTER UPDATE AS SELECT table1.key from table1
inner join inserted on table1.key = inserted.key
When linq-to-sql runs the update command, it also runs a select statement to receive the auto generated values in the same query and expecting the first record set to contains the columns "asked for" but in this case the first row was the columns from the select statement in the trigger. So linq-to-sql was expecting two autogenerated columns, but it only received one column (with wrong data) and that was causing this exception.