Npgsql support for getting jsonb field as stream - postgresql

I am trying to do the following on a jsonb field:
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
using (var results = reader.GetStream(0))
{
results.CopyTo(stream);
}
}
reader.Close();
}
and getting an exception telling me that GetStream is not supported for this field.
Am I missing something here or is it Npgsql that simply doesn't support streaming jsonb fields (yet)?

This is already handled in the next version of Npgsql, 3.1. Unfortunately that version is still in alpha, hopefully I'll be able to release a beta in around two months.
In the meantime you can work around this by reading the jsonb as a string, and if needed, wrapping a TextReader around it (may not be as efficient but will work).

Related

MongoDB - Execute a command conditionally

I need to execute a command that is part of my migration scripts (mongock java library) conditionally based on Mongo version
In case Mongo version is lower then 4.2 I need to execute this command. For Mongo 4.2 and higher it should not be executed.
db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )
Is there a way how to do it?
Thank you,
Lukas
don't know if you already found a solution for this.
The idea is to figure out the Mongo's version inside the changeSet and then perform the required actions.
I will assume you are using the last Mongock's release for version 3.x.x, which is 3.3.2 or 4.0.x.alpha, so you should use MongockTemplate, instead of MongoTemplate. Don't worry, it's just a wrapper/decorator, you won't miss anything from the original API.
So you can do something like this:
#ChangeSet(id = "changeset-1", order = "001", author = "mongock")
public void changeSet(MongockTemplate mongockTemplate, ClientRepository clientRepository) {
String version = mongockTemplate.executeCommand(new Document("buildinfo", new BsonString("")))
.get("version")
.toString();
if(getNumericalVersion(version) < 42) {
//do your actions
} else {
//do you other actions
}
}
NOTE 1: We don't recommend using executeCommand. In this case, for taking the version it's fine, but in general we recommend not using it, specially for writes.
NOTE 2: Currently we are working on version 4, which will allow to scan multiple packages and even isolated ChangeLog classes. So another approach would be to take the version in the bean creation and inject the change or not depending on the MongoDB's version

Cannot set UDTs in a jooq insert, consistently getting a StackOverflowError

The SQL is pretty simple:
CREATE TYPE audit_fields AS (
creation_time_ms BIGINT
);
CREATE TABLE users(
...
audit AUDIT_FIELDS NOT NULL
);
These are two ways I have tried to do this:
UsersRecord getRecord() {
return new UsersRecord()
.setSomeField(...)
.setOtherField(...)
.setAudit(new AuditFieldsRecord(System.currentTimeMillis()));
}
create.insertInto(Tables.USERS)
.set(getRecord())
.execute();
And, this:
create.insertInto(Tables.USERS)
.set(getRecord())
.set(Tables.USERS.AUDIT, new AuditFieldsRecord(System.currentTimemillis()))
.execute();
I am simply getting a StackOverflowError, with the following block repeating throughout (obviously an infinite-recursion):
at org.jooq.impl.UDTConstant.<init>(UDTConstant.java:62)
at org.jooq.impl.DSL.val(DSL.java:12781)
at org.jooq.impl.DSL.val(DSL.java:12732)
at org.jooq.impl.DSL.inline(DSL.java:12590)
at org.jooq.impl.UDTRecordImpl.toString(UDTRecordImpl.java:141)
at java.lang.String.valueOf(String.java:2994)
at org.jooq.impl.AbstractParam.name(AbstractParam.java:104)
at org.jooq.impl.AbstractParam.<init>(AbstractParam.java:78)
at org.jooq.impl.AbstractParam.<init>(AbstractParam.java:74)
at org.jooq.impl.UDTConstant.<init>(UDTConstant.java:62)
at org.jooq.impl.DSL.val(DSL.java:12781)
at org.jooq.impl.DSL.val(DSL.java:12732)
at org.jooq.impl.DSL.inline(DSL.java:12590)
at org.jooq.impl.UDTRecordImpl.toString(UDTRecordImpl.java:141)
at java.lang.String.valueOf(String.java:2994)
at org.jooq.impl.AbstractParam.name(AbstractParam.java:104)
at org.jooq.impl.AbstractParam.<init>(AbstractParam.java:78)
at org.jooq.impl.AbstractParam.<init>(AbstractParam.java:74)
at org.jooq.impl.UDTConstant.<init>(UDTConstant.java:62)
at org.jooq.impl.DSL.val(DSL.java:12781)
at org.jooq.impl.DSL.val(DSL.java:12732)
at org.jooq.impl.DSL.inline(DSL.java:12590)
at org.jooq.impl.UDTRecordImpl.toString(UDTRecordImpl.java:141)
at java.lang.String.valueOf(String.java:2994)
at org.jooq.impl.AbstractParam.name(AbstractParam.java:104)
at org.jooq.impl.AbstractParam.<init>(AbstractParam.java:78)
at org.jooq.impl.AbstractParam.<init>(AbstractParam.java:74)
at org.jooq.impl.UDTConstant.<init>(UDTConstant.java:62)
Any idea what I am doing wrong?
This is an issue that exists in older versions of Jooq 3.7.0. For projects who are using that version and cannot migrate easily to newer versions, this question might be a starting point, so I am not voting to close it (other's are requested to if they see fit).
Upgrading to a later version of jooq fixes this issue.

Identify Code Origin from EF-Generated SQL?

What is the best way to identify the source of a (very) inefficient Entity Framework query when I only have the captured SQL available?
Assuming you're using some kind of logging framework, you could do something like this in your DbContext constructor:
this.Database.Log = sql =>
{
if (sql.Contains(/* part of the offending query */))
{
Logger.Log($"Found it! {Environment.StackTrace}")
}
}

Partial Update on MongoDB Error

I'm trying to have a partial update on one of my documents in MongoDB, using C# driver. I've followed the following posts:
How do you update multiple field using Update.Set in MongoDB using official c# driver?
Partial mongodb upsert using the c# driver?
I get the following error when trying to do the update: "Only classes can be mapped currently", in the AutoMapper CreateClassMap class, the type received is System.Collections.Generic.IEnumerable`1[[MongoDB.Bson.BsonElement, MongoDB.Bson]], where it cannot be an interface.
The code I'm using is:
public void UpdateObjectByFields<T>(int id, Dictionary<string, object> modifiedFields)
where T : class
{
var collection = m_MongoDatabase.GetCollection<T>();
var builder = new UpdateBuilder();
foreach (var modifiedField in modifiedFields)
{
builder.Set(modifiedField.Key, modifiedField.Value.ToString());
}
collection.Update(Query.EQ("_id", id), builder);
}
where the T type is a valid collection in the Mongo.
What am I doing wrong?
Thanks,
Nir
Got this to work, apparently I was using some old dlls for the C# driver.
Fixed it by using the dlls from here:
https://github.com/mongodb/mongo-csharp-driver/downloads
Thanks,
Nir.

XML serialization errors when trying to serialize Entity Framework objects

I have entities that I am getting via Entity Framework. I'm using Code-First so they're POCOs. When I try to XML Serialize them using XmlSerializer, I get the following error:
The type
System.Data.Entity.DynamicProxies.Song_C59F4614EED1B7373D79AAB4E7263036C9CF6543274A9D62A9D8494FB01F2127
was not expected. Use the XmlInclude
or SoapInclude attribute to specify
types that are not known statically.
Anybody got any ideas on how to get around this (short of creating a whole new object)?
Just saying POCO doesn't really help (especially in this case since it looks like you're using proxies). Proxies come in handy in a lot of cases but make things like serialization more difficult since the actual object being serialized is not really your object but an instance of a proxy.
This blog post should give you your answer.
http://blogs.msdn.com/b/adonet/archive/2010/01/05/poco-proxies-part-2-serializing-poco-proxies.aspx
Sorry, I know I'm coming at this a bit late (a couple YEARS late), but if you don't need the proxy objects for lazy loading, you can do this:
Configuration.ProxyCreationEnabled = false;
in your Context. Worked like a charm for me. Shiv Kumar actually gives better insight into why, but this at least will get you back to work (again, assuming you don't need the proxies).
Another way that works independent of the database configuration is by doing a deep clone of your object(s).
I use Automapper (https://www.nuget.org/packages/AutoMapper/) for this in my code-first EF project. Here is some sample code that exports a list of an EF objects called 'IonPair':
public bool ExportIonPairs(List<IonPair> ionPairList, string filePath)
{
Mapper.CreateMap<IonPair, IonPair>(); //creates the mapping
var clonedList = Mapper.Map<List<IonPair>>(ionPairList); // deep-clones the list. EF's 'DynamicProxies' are automatically ignored.
var ionPairCollection = new IonPairCollection { IonPairs = clonedList };
var serializer = new XmlSerializer(typeof(IonPairCollection));
try
{
using (var writer = new StreamWriter(filePath))
{
serializer.Serialize(writer, ionPairCollection);
}
}
catch (Exception exception)
{
string message = string.Format(
"Trying to export to the file '{0}' but there was an error. Details: {1}",
filePath, exception.Message);
throw new IOException(message, exception);
}
return true;
}