---
title: 'CHR0029: Redundant .Set(...).To(...) with matching property names'
---

import { Tabs, TabItem } from '@astrojs/starlight/components';

## Rule Description

AutoMap is enabled by default and maps event properties to identically named read model properties. A `.Set(x => x.P).To(e => e.P)` mapping where the source and target property names are the same duplicates what AutoMap already does. Remove the redundant mapping and rely on AutoMap.

## Severity

Warning

## Example

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
using Cratis.Chronicle.Events;
using Cratis.Chronicle.Projections;

public record Chr0029Customer(string Name);

[EventType]
public record Chr0029CustomerRegistered(string Name);

public class Chr0029CustomerProjection : IProjectionFor<Chr0029Customer>
{
    public void Define(IProjectionBuilderFor<Chr0029Customer> builder) =>
        builder.From<Chr0029CustomerRegistered>(customer => customer
            // Warning CHR0029: '.Set(x => x.Name).To(e => e.Name)' is redundant — AutoMap already maps
            // identically named properties. Remove the mapping.
            .Set(x => x.Name).To(e => e.Name));
}
```

</TabItem>
</Tabs>

## Why This Rule Exists

`.Set(...).To(...)` is for the cases AutoMap cannot infer — a read model property whose name differs from the event property that feeds it. When both lambdas name the *same* property, the mapping restates the default AutoMap already applies, so the line carries no information and only obscures the mappings that do matter.

The analyzer is deliberately conservative: it fires only when both lambdas are simple `param => param.Member` member accesses and the two names are identical. A mapping that renames (`Set(x => x.DisplayName).To(e => e.Name)`) or transforms the value is doing real work and is left alone.

## Related Rules

- **CHR0028** — an explicit `.AutoMap()` call, which is redundant for the same reason.
- [Model-bound projections](/chronicle/projections/model-bound/) — the full reference.
