I have a project class, and related to it I have a categories class and responsible class. When I want to add a project object to database, I call a method from the categories class to get the categories id, and do the same for the responsible class. I mean:
int categoryId = getCategoryId("Beverages");
int responsibleId = getResponsibleId("An Example Name");
These two methods are in different classes, but use similar code. When I run the program I get the error:
"There is already an open DataReader associated with this Command which must be closed first."
You must either fix your code, so that only one active (open) DataReader-object its active on a single DbConnection or enable MARS in your connection string (MultipleActiveResultSets=True).
I do agree with Mithrandir here, but there is another workaround for your question; I suppose methods you listed access to the database (silly, I know , but bare it with me ), and they all open connection to same database. What you should add in your code is an final block,which closes database connection, after transaction is executed:
try
{
string sql="select * from ...."
connection.Open();
comand.CommandText = sql;
comand.ExecuteNonQuery();
}
catch(SQLException)
{
}
finally
{
if (connection!=null)
{
connection.Close();
}
}
Related
I've seen numerous old posts about this but no clear solution.
We use PostGreSQL 9.3 with PostGIS 2; NHibernate 3.2.0-GA with Npgsql 2.1.2.
We have an ASP.NET website witch uses MySQL Spatial and we are now in the progress of switching to PostGIS.
My query that fails is send to NHibernate using this code:
string hql = string.Format("select item from {0} item
where NHSP.Intersects(item.Polygon,:boundary)
and item.Layer = :layer", typeof(Data.Item).Name);
IQuery query = CurrentSession.CreateQuery(hql);
query.SetParameter("boundary", boundary, GeometryType);
query.SetParameter("layer", layer);
return query.List<Data.Item>();
This should generate a query like this:
select * from fields
where layer = 'tst'
and st_intersects(polygon,
'0103000020000000000100000005000000F[..]4A40');
But it generates a query like this:
select * from fields
where layer = 'tst'
and st_intersects(polygon,
'0103000020000000000100000005000000F[..]4A40'::text);
Notice the ::text at the end. This results in the following exception:
Npgsql.NpgsqlException: ERROR: 42725: function st_intersects(geometry, text) is not unique
The reason is because the second argument is send as text to PostGIS instead of a geometry.
I've change some code in the NH Spatial library, as suggested elsewhere:
I added these lines to GeometryTypeBase.cs (NHibernate.Spatial)
protected GeometryTypeBase(NullableType nullableType, SqlType sqlTypeOverwrite)
: this(nullableType)
{
this.sqlType = sqlTypeOverwrite;
}
And changed
public PostGisGeometryType()
: base(NHibernateUtil.StringClob)
{
}
into
public PostGisGeometryType()
: base(NHibernateUtil.StringClob, new NHibernate.SqlTypes.SqlType(System.Data.DbType.Object))
{
}
in PostGisGeometryType.cs (PostGIS driver)
When I run my application I now get a cast exception on
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
this.nullableType.NullSafeSet(cmd, this.FromGeometry(value), index);
}
also in GeometryTypeBase.cs (NHibernate.Spatial):
System.InvalidCastException: Can't cast System.String into any valid DbType.
Any suggestion how to fix this is much appreciated.
I've kept on searching and altering my search string I've found the answer in https://github.com/npgsql/Npgsql/issues/201
In NpgsqlTypes.NpgsqlTypesHelper.cs
nativeTypeMapping.AddType("text_nonbinary", NpgsqlDbType.Text, DbType.Object, true);
nativeTypeMapping.AddDbTypeAlias("text_nonbinary", DbType.Object);
needs to be changed to
nativeTypeMapping.AddType("unknown", NpgsqlDbType.Text, DbType.Object, true);
nativeTypeMapping.AddDbTypeAlias("unknown", DbType.Object);
And also my earlier fix to PostGisGeometryType needs to be done.
Now I finally can get my geometry data from PostGIS.
I'm doin a simple query linq to retrieve a label from an optionSet. Looks like the formatted value for the option set is missing. Someone knows why is not getting generated?
Best Regards
Sorry for the unclear post. I discovered the problem, and the reason of the missing key as formattedvalue.
The issue is with the way you retrieve the property. With this query:
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.PaymentTermsCode
}
I was retrieving the correct int value for the option set, but what i needed was only the text. I changed the query this way:
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.FormattedValues["paymenttermscode"]
}
In this case I had an error stating that the key was not present. After many attempts, i tried to pass both the key value and the option set text, and that attempt worked just fine.
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.PaymentTermsCode,
paymenttermscodeValue = d.FormattedValues["paymenttermscode"]
}
My guess is that to retrieve the correct text associated to that option set, in that specific entity, you need to retrieve the int value too.
I hope this will be helpful.
Best Regards
You're question is rather confusing for a couple reasons. I'm going to assume that what you mean when you say you're trying to "retrieve a label from an OptionSet" is that you're attempting to get the Text Value of a particular OptionSetValue and you're not querying the OptionSetMetadata directly to retrieve the actual LocalizedLabels text value. I'm also assuming "formatted value for the option set is missing" is referring to the FormattedValues collection. If these assumptions are correct, I refer you to this: CRM 2011 - Retrieving FormattedValues from joined entity
The option set metadata has to be queried.
Here is an extension method that I wrote:
public static class OrganizationServiceHelper
{
public static string GetOptionSetLabel(this IOrganizationService service, string optionSetName, int optionSetValue)
{
RetrieveOptionSetRequest retrieve = new RetrieveOptionSetRequest
{
Name = optionSetName
};
try
{
RetrieveOptionSetResponse response = (RetrieveOptionSetResponse)service.Execute(retrieve);
OptionSetMetadata metaData = (OptionSetMetadata)response.OptionSetMetadata;
return metaData.Options
.Where(o => o.Value == optionSetValue)
.Select(o => o.Label.UserLocalizedLabel.Label)
.FirstOrDefault();
}
catch { }
return null;
}
}
RetrieveOptionSetRequest and RetrieveOptionSetResponse are on Microsoft.Xrm.Sdk.Messages.
Call it like this:
string label = service.GetOptionSetLabel("wim_continent", 102730000);
If you are going to be querying the same option set multiple times, I recommend that you write a method that returns the OptionSetMetadata instead of the label; then query the OptionSetMetadata locally. Calling the above extension method multiple times will result in the same query being executed over and over.
I have been trying desperately to delete an item from the database but have so far been unable to get it to work. The error message I see is this one:
"The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable."
I am using EF4.1, with EDMX (Database first) and POCO objects. I have a repository for each type and a general repository that implements the base methods.
The specific problem is when I want to delete an item. Deleting the children is not a problem - everything works perfectly - the problem is when I come to delete the entity itself.
Consider the following model. I have an entity "Foo" which has a 1 to many relationship with "Bar". I call the following method in my repository:
public override void Delete(Models.Foo entity)
{
//Load the child items...
base.Context.Entry(entity).Collection(x => x.Bars).Load();
//Bar
BarRepository barRep = new BarRepository();
foreach (var item in entity.Bars)
{
var obj = barRep.GetById(item.ID);
barRep.Delete(obj);
}
barRep.Save();
//First attempt
//base.Delete(entity);
//base.Save();
//Have to resort to some SQL
base.ExecuteSqlCommand(string.Format("delete from Foo where ID = {0}", entity.ID));
}
The GenericRepository "Delete" method is:
public virtual void Delete(T entity)
{
_entities.Set<T>().Remove(entity);
}
The GenericRepository "Save" method is simply:
public virtual void Save()
{
_entities.SaveChanges();
}
What I would like to get to work is this:
//First attempt
//base.Delete(entity);
//base.Save();
But unfortunately the only way (currently) for me to delete the item is to run some SQL which just calls _entities.Database.ExecuteSqlCommand(SQL).
I've read a lot of things but nothing seems to work. I would really appreciate some help in trying to understand what is going on.
Thanks,
Jose
Hi guys and girls:) I have a question about parralelism and ms sql in C#
I have method that looks into Db for specific object. If it not exists it will add it to Db. Unfortunately it is done with Parallel.ForEach, so I have had some situation, using thread A and B:
A: look for entity with code 'xxx' - result: Not Exist
B: look for entity with code 'xxx' - result: Not Exist
A: Add entity to Db - result OK
B: Add entity to Db - result: "Violation of UNIQUE KEY constraint (...) The duplicate key value is 'xxx' "
what should I do to avoid that situation ?
For do not have this duplicate error, you want to catch here
try{
//execute you insert in base
}catch(Exception ex){
// If your constraint is not respected, an error is thrown.
console.WriteLine("db error : "+ex.Message);
}
But, it's temporary, It's functionnaly, but it's bad, it's not proper...
For have a proper code, you want to create a spooler:
class Spooler{
public System.Collections.Generic.List<String> RequestList = new System.Collections.Generic.List<String>();
public Spooler(){
// Open you Database
// Start you thread will be verify if a request adding in the collection
SpoolThread = new Thread(new ThreadStart(SpoolerRunner));
SpoolThread.Start();
}
public createRequestDb(String DbRequest){
RequestList.Add(DbRequest);
}
private void SpoolerRunner()
{
while (true)
{
if (RequestList.Count() >= 1){
Foreach (String request in RequestList){
// Here, you want to verify your request, if args already exist
// And add request in Database
}
}
// Verify is request exist in the collection every 30 seconds..
Thread.Sleep(30000);
}
}
}
Why using a spooler?
just because, when you initialize you spooler before call you threads, you want to call spooler in every threah, and, for each request, you adding request in collection, and, the spooler will process one after another... and not in the same time in every different threads...
EDIT:
This spooler is a sample, for insert a string request one by one in your database,
you can create a spooler with a collection for your object in you want, and insert in db if not exist... It's just a sample for a solution, when you have many threads, to have a treatments one after another ^^
I have a question regarding P2P with flex.
When passing data between two applications using P2P. I get the following error:
warning: unable to bind to property 'piece' on class 'Object' (class is not an IEventDispatcher)
I've spent a few days using Google to try and find a solution, but a can't get rid of that error. I've tried using ObjectUtils, direct assignment, and creating a new ArrayCollection WITH the ObjectUtils inside the parenthesis and still can't solve the problem.
Purpose of code:
-> Two users connect via P2P
-> 1st user can manipulate pictures (stored as objects in the array collection).
-> 1st user sends updated ArrayCollection (with changed pictures) to 2nd user
-> 2nd user's ArrayCollection gets updated and now sees manipulated pics
As far as my knowledge of Flex goes (fairly new to it), I properly Binded what needed to be binded. Using pop-ups and trace, I was able to see that the data from the ArrayCollection gets copied in properly, but it just doesn't want to display.
Here are some snippets of my code:
[Bindable]
public var taken:ArrayCollection = new ArrayCollection ([
new picLayout(1,'sky.png'),
new picLayout(2,'bird.png')
])
public function receiveSomeData(pass:ArrayCollection):void
{
// Want to replace current version of variable "taken" with
// the one passed in using P2P
this.taken= new ArrayCollection(pass.source);
}
public function sendSomeData(free:ArrayCollection):void
{
sendStream.send("receiveSomeData",free);
}
<s:Button click="sendSomeData(taken)" label="Update" />
Thank You for your help and time!
I figured out what the problem was and how to fix it - with partial thanks to these pages:
Unable to Bind warning: class is not an IEventDispatcher
Flex Warning: Unable to bind to property 'foo' on class 'Object' (class is not an IEventDispatcher)
I knew that the information was being successfully sent to the other peer, but the problem was that the objects INSIDE the ArrayCollection weren't made bindable.
My solution to the problem was as follows:
Create a loop that sends each object in the ArrayCollection along with an index that tells you what value in the ArrayCollection you are streaming.
Now, since you are "streaming" the data, overwrite the current ArrayCollection, using the setItemAt() function with first field as "new ObjectProxy(passedObject)" and the second field as the passedIndex (Note): the ObjectProxy() function forces the passed object to be bindable.
Here is an updated snippet of my code:
[Bindable]
public var takenPics:ArrayCollection = new ArrayCollection ([
new picLayout(1,'sky.png'),
new picLayout(2,'bird.png')
])
private function sendSomeData(data:Object, index:int):void
{
sendStream.send("receiveSomeData",data,index);
}
private function receiveSomeData(passedPic:Object,ix:int):void
{
// ObjectProxy needed to force a bindable object
takenPics.setItemAt(new ObjectProxy(passedPic),ix);
}
public function sendPictures():void
{
// ix < 2 because size of ArrayCollection is 2
for (var ix:int = 0; ix<2; ix++)
sendSomeData(takenPics[ix],ix);
}