Entities

Entity definitions need to follow certain rules in order to work with Xams.

Entity Rules

  1. Entities must have a string Name field or a string field with the attribute UIName for lookup fields.
  2. Composite Primary Keys are not supported.
  3. Self-referencing entities must NOT include navigation properties to themselves.
  4. System entities use base table names: User, Team, Role, Setting are always the table names—even when extended (e.g., public class AppUser : User → table name is "User" for queries and permissions).

Field Types: UIOption vs Enums

Never use C# enums for user-facing choice fields. Always use [UIOption("GroupName")] instead.

Project / Entities / Post.cs

[Table(nameof(Post))]
public class Post : BaseEntity
{
public Guid PostId { get; set; }
[UIName]
public string Title { get; set; }
// ✅ CORRECT - Use UIOption for choice fields
[UIOption("PostStatus")]
public string Status { get; set; } = "Draft";
// ❌ WRONG - Don't use enums
// public PostStatus Status { get; set; }
}

Why UIOption?

  • Options are manageable via Admin Dashboard without code changes
  • Supports dropdown UI components automatically
  • Values can be added/modified at runtime
  • See Attributes for UIOption setup details

Self-Referencing Entities

For entities that reference themselves (like nested comments), use only the ID field - do not include the navigation property.

Project / Entities / Comment.cs

[Table(nameof(Comment))]
public class Comment : BaseEntity
{
public Guid CommentId { get; set; }
[UIRequired]
public string Content { get; set; }
// Self-reference - use ID only
public Guid? ParentCommentId { get; set; }
// ❌ Do NOT add: public Comment? ParentComment { get; set; }
}

Cascade Delete

Configure cascade delete using the nullable operator ? and the CascadeDelete attribute.

Project / Entities / Widget.cs

[Table(nameof(Widget))]
public class Widget : BaseEntity
{
public Guid WidgetId { get; set; }
// Name is not nullable and required
[UIName]
public string Name { get; set; }
// Company is not nullable making it required
// Deleting the Company deletes this record
public Guid CompanyId { get; set; }
public Department Company { get; set; }
// Manufacturer is nullable making it optional
// Deleting the Manufacturer sets this to null
public Guid? ManufacturerId { get; set; }
public Manufacturer? Manufacturer { get; set; }
// Contact is nullable but the UIRequired attribute makes it required
// Deleting the contact sets this to null
[UIRequired]
public Guid? ContactId { get; set; }
public Contact Contact { get; set; }
// Address is nullable making it optional
// The CascadeDelete attribute deletes this
// record when the Address is deleted
[CascadeDelete]
public Guid? AddressId { get; set; }
public Address Address { get; set; }
}

Was this page helpful?