1

我从我的 SQL Azure 数据库获取时间戳(行版本)时遇到问题。在我的表中有一个数据类型为时间戳的列。这个时间戳与日期时间不同,它更像是一个行版本。我可以通过MobileServiceTable的查询得到这个表中的所有其他数据,没有问题。但是这种特殊的数据类型是个问题。我的这个表的类看起来像:

public class ArbeitsgangBezeichnung {
    @com.google.gson.annotations.SerializedName("id")
    private int ID;
    @com.google.gson.annotations.SerializedName("ABZ_ArbeitsgangBezeichnungID")
    private int ABZ_ArbeitsgangBezeichnungID;
    @com.google.gson.annotations.SerializedName("ABZ_Bezeichnung")
    private String ABZ_Bezeichnung;
    @com.google.gson.annotations.SerializedName("ABZ_RowVersion")
    private StringMap<Number> ABZ_RowVersion;
    //constructor, getter, setter, etc....
}

如果我在 Azure 中登录并查看表格,则有我的示例值和自动生成的时间戳。时间戳值看起来像“AAAAAAAAB/M=”。如果我登录 sql 数据库并让我显示数据,那么对于时间戳,只有“二进制数据”(在尖括号中)而不是 Azure 中显示的那个值。

变量“ABZ_RowVersion”应包含此时间戳,但 StringMap 中的数据与 Azure 中的不同。我尝试将 String 和 Byte 作为 StringMap 的数据类型,但没有帮助。

我为 ABZ_RowVersion 尝试了 byte[],但后来我在回调方法中遇到了异常。然后我尝试了 ABZ_RowVersion 的 Object,那时我发现它是一个 StringMap,但仅此而已。

有谁知道,如何从时间戳中获取数据,我需要它进行比较。

已经谢谢了

4

1 回答 1

1

当您在表中创建timestamp列时,它本质上是一varbinary(8)列。在节点 SQL 驱动程序中,它被映射到一个Buffer类型(通常用于二进制数据的 node.js 类型)。您看到的对象 ( {"0":0, "1":0, ..., "length":8}) 是将缓冲区字符串化为 JSON 的方式。该表示不会映射到 Android 中 Gson 序列化程序的默认字节数组表示(或byte[]托管代码中的 )。

为了能够使用时间戳列,您需要做的第一件事是“教”序列化程序如何理解服务器返回的列的格式。你可以用一个JsonDeserializer<byte[]>类来做到这一点:

public class ByteArrayFromNodeBufferGsonSerializer
    implements JsonDeserializer<byte[]> {

    @Override
    public byte[] deserialize(JsonElement element, Type type,
            JsonDeserializationContext context) throws JsonParseException {
        if (element == null || element.isJsonNull()) {
            return null;
        } else {
            JsonObject jo = element.getAsJsonObject();
            int len = jo.get("length").getAsInt();
            byte[] result = new byte[len];
            for (int i = 0; i < len; i++) {
                String key = Integer.toString(i);
                result[i] = jo.get(key).getAsByte();
            }
            return result;
        }
    }
}

现在您应该可以读取数据了。不过,还有另一个问题。在插入和更新操作中,列的值由客户端发送,SQL 不允许您在其中设置它们。所以让我们上这门课:

public class Test {
    @SerializedName("id")
    private int mId;

    @SerializedName("name")
    private String mName;

    @SerializedName("version")
    private byte[] mVersion;

    public int getId() { return mId; }
    public void setId(int id) { this.mId = id; }

    public String getName() { return mName; }
    public void setName(String name) { this.mName = name; }

    public byte[] getVersion() { return mVersion; }
    public void setVersion(byte[] version) { this.mVersion = version; }
}

在插入和更新操作中,我们需要在服务器端脚本中做的第一件事是从对象中删除该属性。还有另一个问题:插入完成后,运行时不返回 rowversion 属性(即,它不更新item变量。所以我们还需要对数据库执行查找以检索该列:

function insert(item, user, request) {
    delete item.version;
    request.execute({
        success: function() {
            tables.current.lookup(item.id, {
                success: function(inserted) {
                    request.respond(201, inserted);
                }
            });
        }
    });
}

更新时也是如此:

function update(item, user, request) {
    delete item.version;
    request.execute({
        success: function() {
            tables.current.lookup(item.id, {
                success: function(updated) {
                    request.respond(200, updated);
                }
            });
        }
    });
}

现在,这肯定是很多工作——对这种类型的列的支持应该更好。我在http://mobileservices.uservoice.com/forums/182281-feature-requests/suggestions/4670504-better-support-for-timestamp-columns的 UserVoice 页面中创建了一个功能请求,所以请随意投票帮助团队优先考虑它。

于 2013-10-18T16:50:17.687 回答