# Has anyone made an ORM work with Ignition transaction groups?

**URL:** <https://forum.inductiveautomation.com/t/has-anyone-made-an-orm-work-with-ignition-transaction-groups/64665>\
**Category:** Ignition\
**Tags:** ignition81\
**Created:** [September 29, 2022, 3:47pm UTC](https://forum.inductiveautomation.com/t/has-anyone-made-an-orm-work-with-ignition-transaction-groups/64665 "2022-09-29T15:47:32Z")\
**Posts on this page:** 1\
**Showing post:** 5

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [September 29, 2022, 6:48pm UTC](https://forum.inductiveautomation.com/t/has-anyone-made-an-orm-work-with-ignition-transaction-groups/64665/5 "2022-09-29T18:48:28Z")

</div>

I've long been using a "SmartMap" extended dictionary that naturally allows property access to dictionary content. Create one with a tuple sequence of colName/colValue pairs and you suddenly have a very ORM-like row object. The one I like most delivers a `None` for missing keys automatically:

```auto
#----------
# Handy tool for objects as "bags of properties"
# by Peter Norvig, enhanced as a subclass of dict() by Philip J. Turmel
# http://norvig.com/python-iaq.html
class SmartMap(dict):
	def __repr__ (self):
		args = []
		for (k,v) in self.items():
			if isinstance(v, basestring):
				args.append('%s=%s' % (k, v))
			else:
				try:
					z = len(v)
					args.append('%s=%s' % (k, type(v)))
				except:
					args.append('%s=%s' % (k, repr(v)))
		return 'SmartMap(%s)' % ', '.join(args)
	def __str__ (self):
		args = []
		for k,v in self.items():
			if isinstance(v, basestring):
				args.append('%s=%s' % (k, v))
			else:
				try:
					z = len(v)
					args.append('%s=%s' % (k, repr(v)))
				except:
					args.append('%s=%s' % (k, str(v)))
		return 'SmartMap(%s)' % ', '.join(args)
	def clone(self):
		return type(self)(**self)
	def __getattr__ (self, attr):
		if attr.startswith('__'):
			raise AttributeError(attr)
		if attr in self:
			return self[attr]
		return None
	def __setattr__ (self, attr, val):
		if attr.startswith('__'):
			super. __setattr__ (self, attr, val)
		self[attr] = val

```

If you have a dataset `ds` and `rowNum`, you can load that row into this model like so:

```auto
row = util.SmartMap(zip(ds.columnNames, [ds.getValueAt(rowNum, i) for i in range(ds.columnCount)]))

```

If you consistently use column names that are valid python identifiers (and you do, right?), everything in the row is now accessible as either `row.colName` or `row["colName"]`, as needed.

I'd be delighted if the future PyDataset Jython proxy supported this syntax in its row iterator...

---

_[View the full topic](https://forum.inductiveautomation.com/t/has-anyone-made-an-orm-work-with-ignition-transaction-groups/64665)._
